考虑以下代码:
template<typename F>
struct S;
template<typename Ret, typename... Args>
struct S<Ret(Args...)> { };
template<typename... Args>
using Alias = S<void(Args...)>;
int main() {
S<void(int)> s;
Alias<int> alias;
}
它工作正常,正如预期的那样,涉及S
的行和涉及Alias
的行都在引擎盖下定义了相同类型的S
现在,考虑以下更改:
int main() {
S<void(void)> s; // this line compiles
Alias<void> alias; // this line does not
}
我希望它能够编译,原因与上面提到的类似
不用说,它没有编译,因为这行涉及别名,相反,我得到了错误:
替换“模板使用别名=S[参数={void}]”
[…]
错误:无效的参数类型“void”
问题很简单:我错过了什么?
源自[dcl.fct],强调我的:
由非依赖类型val
的单个未命名参数组成的参数列表等价于空参数列表。除此特殊情况外,参数不得具有cvval
类型。
在这种情况下,Args...
是一个依赖类型包,因此那里不允许val
。这个想法在[temp.deduct]的注释中重复:
[注:类型扣减可能因以下原因失败:
-[…]
-试图创建一个函数类型,其中参数的类型为void,或返回类型为函数类型或数组类型
-[…]
-结束注释]
注意S
至少有一个简单的解决方法,您可以只编写
Alias
在C++98中,局部类和未命名类不能作为模板参数,这或许是一个负担,C++11则放宽了这方面的限制: void f(vector<X>& v) { struct Less { bool operator()(const X& a, const X& b) { return a.v<b.v; } }; // C++98: 错误: Less是局部
另一个有用的可能示例:(伪代码)
我试图在类型s. t上专门化一个类。它忽略了给定类型的恒定性。在这种情况下,该类型是一个模板模板参数: 上面的代码在GCC 4.8.4和clang 5.0(with-std=c 11)中都抱怨bar在与匹配FOFType模板参数化的类一起使用时未定义。即使我删除了sfinae参数,仍然无法找到特化。 这个问题的一个例子可以在这里找到:https://godbolt.org/g/Cjci9C.在上面
假设我有一个模板类Foo,具有两个模板参数和一个模板成员函数。 我想在模板类是部分专门化的情况下进行成员函数专门化,但以下代码被g编译失败 G说: 错误:在' 模板 我试过了 而g抱怨更多 能不能可能,怎么做?
上节的 Sstack 类模扳只用模板首部的类型参数,也可以使用无类型参数(non-type parameter),无类型参数可以有默认参数,一般将无类型参数当作Const处理。例如,模板首都可以取 int elements 参数,如下所示: template<class T,int elements> // note non-type parameter 然后下列声明: Stack<double,
考虑下面粘贴的代码。我定义了一个非常简单的类,编译器为其生成一个隐式推导指南,这样就可以在没有显式模板参数的情况下构造它。但是,模板参数推导不适用于从仅直接转发到目标类的简单别名模板构造对象: 正如您从上面的代码注释中看到的,g给了我一个关于使用别名模板而没有模板参数的错误。我希望在这样的例子中,模板参数推导会被转发。 所以,我的问题是:这是通过明示设计目前的措辞来对班级模板的论点进行演绎的建议吗