【发布时间】:2021-11-24 06:27:03
【问题描述】:
这是说明问题的设置。
template <typename T>
struct opt {
const char* name;
T x;
template <typename X>
opt(const char* name, X&& x)
: name(name), x(std::forward<X>(x)) { }
};
template <typename T>
opt(const char*, T&&) -> opt< some_type_transformation<T> >;
template <typename... T>
void function(opt<T>&&... opts) {
// do something with the passed arguments
}
这样,可以使用以下语法。
function(opt("a",1),opt("b",2.),opt("c",3u));
但以下不起作用。
function({"a",1},{"b",2.},{"c",3u});
理论上,有足够的信息来确定在第二种情况下要做什么,因为function 只接受opt<T> 类型的参数,而T 可以使用定义的推导指南进行推导。
可以做些什么来启用第二种更简洁的语法吗?
【问题讨论】:
-
opt不是聚合;它有一个构造函数(虽然我不确定为什么)。但即使它是一个聚合,这也行不通。 -
也许我没有直截了当的术语。我指的是
{ }的使用,但没有将类型明确命名为“聚合初始化”,而不是将opt命名为“聚合”。opt有一个构造函数,因为这是一个示例。实际上,构造函数可能会做一些不平凡的事情。 -
如果“聚合初始化”仅指聚合的初始化,那我就不好了。不要过多地阅读实现细节。我要做的就是将有序的参数集传递给函数,并从集合的元素之一推导出类型。
-
"我指的是 { } 的使用,但没有明确将类型命名为“聚合初始化”" 这只是 list initialization (specifically copy-list-initialization),它可能会调用聚合初始化,具体取决于类型。
-
“有足够的信息来确定在第二种情况下该怎么做” - 如果您从不包含任何其他带有接受 3“事物的函数(模板)的标题”。那么它就不再是足够的信息了。更不用说有时还需要考虑 ADL。最终,当新声明出现在大多数不相关的范围内时,该标准的动机是反对改变行为。在“明显”的情况下失败是关于一致的行为。
标签: c++ templates c++20 template-argument-deduction list-initialization