我有以下示例:
#include <array>
struct A {
const char* str;
const char* str2;
};
template<size_t N>
struct As {
std::array<A,N> elems_;
};
template<class... Args>
As(Args...)->As<sizeof...(Args)>; //<-- NOTE: deduction guide !
constexpr static As as{A{"a","b"}, A{"1","2"}};//<-- 'retyping' A here
int main() {
return as.elems_.size();
}
尽管此代码有效,但我想避免在汇总列表中对A
进行“重新键入”,但是如果我忽略了它,则推导指南将失败,并显示:"cannot deduce template arguments for 'As'"
(其中,我想这很有道理。解决此问题的一种方法是通过手写我需要的任意数量的扣除指南,此后,我可以在每个扣除指南中写入A
类型(即:针对我需要的每种尺寸的容器进行一次扣除)
答案 0 :(得分:5)
嵌套聚合初始化具有或多或少令人惊讶的行为,您不要添加嵌套的{
/ }
来进行匹配。
例如,this是初始化std::array<std::array<int, 2>, 2>
的方式:
std::array<std::array<int, 2>, 2> arr = { 1, 1, 2, 2 };
做{ {1, 1}, {2, 2} }
可以not起作用!
类似地,在您的情况下,聚合初始化将不需要嵌套的{
/ }
且CTAD已经完成(嗯,给定的模板参数):
constexpr static As<2> as{"a","b", "1","2"}; // Ok!
认识到这一点,我们可以添加以下推导指南:
template<class ... Ts>
As(Ts...) -> As<(sizeof...(Ts) + 1)/2>;
这将选择N
作为“一半参数”。实际上,现在您可以像这样初始化:
constexpr static As as{"a","b", "1","2"}; // Deduces N = 2.
演示:https://godbolt.org/z/oznEwl
是的,为了获得更好的可读性,这失去了使用{
/ }
来结构化输入的能力,但是我在这里指责聚合初始化(请参见上面的嵌套数组示例)。