标题有点令人困惑,但我的意思是这种特殊情况:

template<class>
struct get_type_of_nontype;

template<class T, T Value, template<T> class Template>
struct get_type_of_nontype<Template<Value>> {
    using type = T;
};

所以我可以这样使用它:
#include <type_traits>

template<int I>
class int_non_type {};

static_assert(
    std::is_same<typename get_type_of_nontype<int_non_type<0>>::type, int>::value,
    "T is deduced to be `int` as `template<T> class Template` is `template<int> class int_non_type`"
);

在C++ 17中可以正常工作。在C++ 14中,出现以下错误:

gcc 8:
<source>:5:8: error: template parameters not deducible in partial specialization:
struct get_type_of_nontype<Template<Value>> {
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:8: note:         'T'

lang声7:
<source>:5:8: error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct get_type_of_nontype<Template<Value>> {
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:4:16: note: non-deducible template parameter 'T'
template<class T, T Value, template<T> class Template>
               ^

然后他们俩都抱怨struct get_type_of_nontype<int_non_type<0>>不完整,因此typename get_type_of_non_type<int_non_type<0>>::type无法编译。

为什么C++ 14和C++ 17之间有区别?这只是一个编译器错误吗?如果没有,是否有办法在C++ 14中做到这一点?

最佳答案

[temp.deduct.type]第13和14段中的标准措词已更改。所以是的,您的示例在C++ 14中无效,但由于具有新的语言功能,因此在C++ 17中是允许的。
C++ 14:

C++ 17:

这似乎与另一个C++ 17模板更改有关:C++ 17是第一个允许在非类型模板参数中使用占位符类型的版本,例如template <auto Value>template <auto* Ptr>。我希望编译器实现需要一些类似的逻辑来支持这两种语言功能。

关于c++ - 模板模板类中的非类型参数的类型在C++ 14中不可推论,但在C++ 17中可推论,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55033649/

10-16 19:10