当命名的 lambda 用作模板类参数或构造函数参数时,类模板无法编译
class template fails to compile when named lambda is used as template class argument or constructor argument
我目前正在试验类模板编程,在传递命名的lambda作为其参数时,我遇到了这种奇怪的行为,我无法理解。有人可以解释为什么下面的(1(和(2(不起作用吗?
template<typename Predicate>
class Test{
public:
Test(Predicate p) : _pred(p) {}
private:
Predicate _pred;
};
int main(){
auto isEven = [](const auto& x){ return x%2 == 0; };
// Working cases
Test([](const auto& x){ return x%2 == 0; });
Test{isEven};
auto testObject = Test(isEven);
// Compilation Error cases
Test(isEven); // (1) Why??? Most vexing parse? not assigned to a variable? I cant understand why this fails to compile.
Test<decltype(isEven)>(isEven); // (2) Basically same as (1) but with a workaround. I'm using c++17 features, so I expect automatic class parameter type deduction via its arguments
return 0;
};
编译器错误消息:与 (1( 和 (2( 相同
cpp/test_zone/main.cpp: In function ‘int main()’:
cpp/test_zone/main.cpp:672:16: error: class template argument deduction failed:
Test(isEven);
^
cpp/test_zone/main.cpp:672:16: error: no matching function for call to ‘Test()’
cpp/test_zone/main.cpp:623:5: note: candidate: template<class Predicate> Test(Predicate)-> Test<Predicate>
Test(Predicate p): _p(p){
^~~~
cpp/test_zone/main.cpp:623:5: note: template argument deduction/substitution failed:
cpp/test_zone/main.cpp:672:16: note: candidate expects 1 argument, 0 provided
Test(isEven);
^
请原谅我的格式,并编译错误消息片段,因为它与确切的行不匹配。我正在使用 g++ 7.4.0,并使用 c++17 功能进行编译。
在C++中,您可以将变量声明为
int(i);
这与
int i;
在您的情况下,线条
Test(isEven);
Test<decltype(isEven)>(isEven);
被编译为好像您正在声明变量 isEven
.我很惊讶您的编译器的错误消息与我希望看到的如此不同。
您也可以使用简单的类重现该问题。
class Test{
public:
Test(int i) : _i(i) {}
private:
int _i;
};
int main(){
int i = 10;
Test(i);
return 0;
};
我的编译器 g++ 7.4.0 的错误:
$ g++ -std=c++17 -Wall socc.cc -o socc
socc.cc: In function ‘int main()’:
socc.cc:15:11: error: conflicting declaration ‘Test i’
Test(i);
^
socc.cc:10:9: note: previous declaration as ‘int i’
int i = 10;
正如您所说,这是一个最令人烦恼的解析问题; Test(isEven);
正在尝试重新定义一个名为 isEven
的变量,并且对于 Test<decltype(isEven)>(isEven);
也是如此。
如您所展示的,您可以使用{}
而不是()
,这是自C++11以来的最佳解决方案;或者您可以添加其他括号(使其成为函数样式转换(。
(Test(isEven));
(Test<decltype(isEven)>(isEven));
住
相关文章:
- C++:使用运算符 = 调用多参数构造函数
- 通过零参数构造函数创建的 glm::mat4 应该包含哪些值?
- 好奇的混合与可变参数构造函数
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 为什么我们需要创建一个单参数构造函数来使用临时的无名称对象
- 在可变参数构造函数中初始化常量数组
- C++ 显式多参数构造函数歧义
- 零一参数构造函数
- 可变参数构造函数中的 SFINAE
- 当没有显式关键字与单参数构造函数一起使用时,编译器可以发出警告
- 可变参数类模板和可变参数构造函数
- 确保模板参数类型与其可变参数构造函数的类型匹配
- C++默认参数构造函数与内联初始化优先级
- 如何在 c++ 中将包含复制构造函数的类的参数构造函数称为私有?
- 自动存储中没有无参数构造函数的类对象和异常
- 警告:用两个参数构造函数返回对象时,表达结果未使用
- 如何在C++中调用无参数构造函数
- 在 c++ 中具有多个参数构造函数的模板类存在问题
- 可变参数构造函数优先于用户提供的移动构造函数,除非默认
- 如何从可变参数构造函数参数构造任何对象?