【发布时间】:2020-09-24 15:15:33
【问题描述】:
C++17 提供class template argument deduction。
我有以下小例子(你可以粘贴到启用 C++17 的 onlinegdb,没问题)在某些情况下它会失败,但我不知道为什么:
#include <iostream>
enum class Res{
ResA,
ResB
};
template<Res>
class B{
};
template<Res T>
class A{
//If I remove this construtor, template type deduction will not work anymore
public:
A(B<T> b){
}
};
template<>
class A<Res::ResA>{
public:
A(B<Res::ResA> b){
std::cout<<"A res A\n";
}
};
int main()
{
B<Res::ResA> b;
A a(b);
}
上面的代码有效。但是,一旦我将A 的构造函数更改为模板特化中的任何其他构造函数,模板参数推导将不起作用,A 必须由A<Res::ResA> 初始化。
我不知所措。为什么会这样?感谢您的任何想法!
【问题讨论】:
-
我猜编译器忽略了参数推导的特化。所以它不可能知道 T 应该是什么。
-
FWIW,为了让自己保持清醒,当你有模板专业化时,假装它不存在。在主模板被解析之前,它们实际上并没有发挥作用,并且仅与与模板专业化匹配的主模板一起使用。在那之前,它只是那些特定模板参数的配方。
-
Elliot,这在语义上有什么不同?
-
@Elliott 在这种情况下没有推论,模板参数只有一个默认值,因此它只会使代码适用于该特定专业化。这并不能真正回答问题或解决 CTAD 的任何问题。它只会编译这个特定的 sn-p 代码。
-
@Elliott 不,编译器不会推断出任何东西。您明确告诉它模板参数应该是
Res::ResA如果它不可推导。如果您要添加另一个模板专业化A<Res::ResB>,它在其构造函数中采用B<Res::ResB>,它将无法工作,因为不涉及实际扣除。只有一个默认值。
标签: c++ templates c++17 template-argument-deduction class-template