4

我有以下示例:

#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在每个推导指南中写下类型(即:我需要的容器的每个尺寸都需要一个推导)。

4

1 回答 1

5

嵌套聚合初始化具有或多或少令人惊讶的行为,您没有添加嵌套{/}来匹配。

例如,是您初始化的方式std::array<std::array<int, 2>, 2>

std::array<std::array<int, 2>, 2> arr = { 1, 1, 2, 2 };

{ {1, 1}, {2, 2} }不行的!

同样,在您的情况下,聚合初始化不需要已经完成 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

是的,这失去了用{/来构造输入以}提高可读性的能力,但我在这里责怪聚合初始化(参见上面的嵌套数组示例)。

于 2019-05-21T11:25:52.457 回答