以下内容无法编译:
struct S {
template <class T> S(T) {}
};
void f(int) {}
int main() {
S(f);
}
g ++ - 4.9说
template.cpp: In function ‘int main()’:
template.cpp:6:8: error: no matching function for call to ‘S::S()’
S(f);
^
template.cpp:6:8: note: candidates are:
template.cpp:2:24: note: template<class T> S::S(T)
template <class T> S(T) {}
^
template.cpp:2:24: note: template argument deduction/substitution failed:
template.cpp:6:8: note: candidate expects 1 argument, 0 provided
S(f);
^
template.cpp:1:8: note: constexpr S::S(const S&)
struct S {
^
template.cpp:1:8: note: candidate expects 1 argument, 0 provided
template.cpp:1:8: note: constexpr S::S(S&&)
template.cpp:1:8: note: candidate expects 1 argument, 0 provided
clang给出了类似的错误。
另一方面,以下编译:
struct S {
template <class T> S(T) {}
};
void f(int) {}
int main() {
S s = S(f); // this line was changed
}
那么这里发生了什么?
答案 0 :(得分:7)
问题
您编写的代码并不代表您的想法,您实际上是在声明名为S
的{{1}}类型的变量;它是不构建f
类型的未命名实体,其中S
为参数。
注意:当您将行更改为f
时,您正在声明名为S s = S(f)
的{{1}}类型的变量,并使用临时值初始化s
(即 S 的 copy-constructor 将用于初始化S
)。
解决方案
在括号中包装类型,或使用 uniform-initialization (在C ++ 11中引入)。
S(f)
s
原因
标准(n3797)表示(S) (f); // creates a temporary of type S initialized with `f`
在声明变量时相当于S { f }; // c++11
,可以在下面的部分中阅读:
8.3p6 声明者的含义
T(x)
在声明
T x
中[dcl.meaning]
的格式为T D
包含的declarator-id的类型与 声明中包含 declarator-id
D
括号不会改变嵌入的 declarator-id 的类型,但是 他们可以改变复杂声明者的绑定。
答案 1 :(得分:0)
使用struct S
int main() {
S(f); // 1 <-----+
S s(f); // 2 <-------+ // +---- SAME
S s1 ; // +---- SAME // 3 <-----+
S s2 = S(f) ; // 4 <-------+
}
f
&amp;分别为s1
的{{1}}需要构造函数进行初始化S
&amp; s
分别使用复制构造函数s2
{注意此处S
不是您的函数名称)