[英]Can C++17's deduced `auto` non-type `template` parameters pattern-match templates with explicit non-type parameters?
考虑这个例子( 也可以在wandbox上使用 ) :
template <template <auto> class>
void test() { }
template <int>
struct X { };
试图在clang++
4.0 (trunk)上实例化test<X>()
)会导致编译错误:
error: no matching function for call to 'test'
test<X>();
^~~~~~~
note: candidate template ignored:
invalid explicitly-specified argument for 1st template parameter
void test() { }
我最初的假设/直觉是test
可用于匹配任何具有非类型参数的template
。
但是,以下代码段成功编译:
template <template <auto> class>
void test() { }
// vvvv
template <auto>
struct X { };
这是有意的吗? 在P0127R2中找不到任何结论。
这绝对是有意的。 模板模板参数只能匹配采用相同类型参数的模板。 这个:
template <template <auto> class>
void test() { }
只能使用可以采用任何类型的非类型参数的类模板进行实例化。 但是这个:
template <int>
struct X { };
不是这样的类模板。 X
只能用int
实例化。 它只是与模板模板参数的规范不匹配,因此错误。 如果test
想用指针类型实例化其类模板怎么办? 或指向函数或指向成员的指针? 那是不可能的。
第二次尝试, template <auto> struct X { };
不匹配模板模板参数,因此是良好的。 另请注意,反过来, test
采用template <int> class
参数并传入template <auto> struct X { };
因为参数比参数更通用,所以格式也很好。
相关措辞在[temp.arg.template]中:
模板个参数的匹配模板的模板参数
P
时各在模板参数的对应的类模板或别名模板的模板参数列表模板参数的A
在模板参数列表对应的模板的参数相匹配P
两个模板参数匹配,如果它们是相同类型(类型,非类型,模板),非类型模板参数 ,它们的类型是等价的(14.5.6.1),对于模板模板参数 ,它们各自对应模板参数以递归方式匹配。
注意:等价措辞接受auto
- auto
情况并拒绝auto
- int
情况,但似乎也拒绝int
- auto
情况(基于我的阅读)。 我将尝试对其进行澄清。
除了Barry的答案,这让我很好奇,以下是使用Clang 4.0(SVN)的四种可能的组合和结果, 另请参阅wandbox :
template <bool> struct obj_bool { }; // object taking a value of boolean type
template <auto> struct obj_auto { }; // object taking a value of deduced type
// ^^^^^^ Note: this is a template value argument (non-type template argument)
template <template <auto> typename> void fn_auto() { }
template <template <bool> typename> void fn_bool() { }
// ^^^^^^^^^^^^^^^^^^^^^^^^ Note: this is a template type argument
// ^^^^^^ taking a template value argument
int main() {
fn_bool<obj_bool>(); // #1 bool->bool OK (exact match)
fn_auto<obj_auto>(); // #2 auto->auto OK (exact match)
fn_bool<obj_auto>(); // #3 bool->auto OK (sub-set)
//fn_auto<obj_bool>(); // #4 auto->bool Error: no matching function.
}
从那以后,#1和#2显然是完全匹配并且按预期工作。 #3将在模板上调用bool实现,该模板不仅可以处理bool而且可以处理所有类型,而#4将尝试调用期望通用对象(auto)的定义,其中对象仅提供可能的子集(bool) 。
模板化函数fn_auto
承诺采用任何值类型(自动)的模板的可能实例化。 因此只给它一个可能性的子集(bool)违反了这个承诺。
虽然不是很明显,但这种限制是有道理的。 抱歉我的措辞不符合C ++标准。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.