为什么这里的大括号和括号初始化有区别?
Why is there a difference between brace and parentheses initialization here?
我正在尝试从本文中重新创建一个关于常见"重载lambda"技巧的简单示例,以创建可与std::visit
或其他类似工具一起使用的重载集。我的简化示例是:
#include <iostream>
#include <vector>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; // (1)
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; // (2)
int main() {
overloaded os(
[](int i) { std::cout << "int: " << i << std::endl; },
[](const char *str) { std::cout << "str: " << str << std::endl; }
);
os(1);
os("Hello world!");
return 0;
}
这不会编译。
<source>: In function 'int main()':
<source>:12:5: error: no matching function for call to 'overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >::overloaded(main()::<lambda(int)>, main()::<lambda(const char*)>)'
12 | );
| ^
<source>:4:30: note: candidate: 'constexpr overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >::overloaded(const overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >&)'
4 | template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; // (1)
| ^~~~~~~~~~
<source>:4:30: note: candidate expects 1 argument, 2 provided
<source>:4:30: note: candidate: 'constexpr overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >::overloaded(overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >&&)'
<source>:4:30: note: candidate expects 1 argument, 2 provided
如果我将overloaded os
的初始化更改为使用大括号初始化,那么它可以工作。谁能解释一下这里的区别?
下面是一个没有任何模板处理的简化示例:
struct A { };
struct B { };
struct C : A, B { };
C x(A{}, B{}); // error
C y{A{}, B{}}; // ok
问题是:C
是一个聚合,因此您可以使用聚合初始化来初始化其组件。这就是y
起作用的原因。但是C
是一个聚合,它没有构造函数,这就是x
初始化试图做的事情。没有这样的匹配构造函数,因此它失败了。请注意,在 C++20 中,x
也将起作用,因为我们将能够使用括号执行聚合初始化。
获取要编译的x
声明的方法是添加一个构造函数:
struct C : A, B {
C(A a, B b) : A(a), B(b) { }
};
或者,对于原始问题:
template<class... Ts>
struct overloaded : Ts... {
overloaded(Ts... ts) : Ts(std::move(ts))... { } // <==
using Ts::operator()...;
};
或者只是坚持聚合初始化,因为这是我们在这里更明确地做的事情。
相关文章:
- 为什么这里的大括号和括号初始化有区别?
- 这些初始化之间有什么区别?
- 两种初始化有什么区别:Foo f();Foo f = Foo()
- 在C++中初始化带有和不使用构造函数调用的对象有什么区别
- 初始化的多维数组,用声明初始化和声明后初始化有什么区别
- 这些在C 中初始化C数组的方式之间有区别吗?
- 在 C++ 中,字符串的这两种不同初始化有什么区别?
- 初始化空字符串的 " " 和 {} 有什么区别?
- 这两个初始化之间有什么区别
- 在 C++ 中:在函数中初始化变量与在函数标头中声明变量有什么区别?
- 这两种初始化成员变量的方法之间有区别吗?
- unique_ptr的初始化有什么问题?
- {x} 和 '= {x}' 初始化之间有什么区别(如果有的话)?
- std::map 的这两种列表初始化形式有什么区别
- 隐式初始化和显式初始化有什么区别
- C++中的构造函数初始化有什么区别?
- std::array的内联初始化有什么问题?
- 在初始化列表中初始化与在构造函数中初始化的区别
- 类和构造函数初始化的区别
- 标准(c++)对编译时初始化有什么规定?