通过显式构造函数

时间:2018-02-12 09:05:54

标签: c++ c++11 aggregate-initialization explicit-constructor

我正在编写一个具有显式构造函数的类,该类采用const char*参数。对于这个问题的意图和目的,它看起来像这样:

struct Symbol
{
    Symbol()=default;
    explicit Symbol(const char*);
};

现在我想编写一个用于初始化数组的文档示例(数组/向量/列表 - 我不关心确切的类型),我需要尽可能简洁明了。理想情况下它看起来像这样:

Symbol symbols[] = { "a", "b", "c"};

因为显式关键字而无法编译,我不准备使构造函数隐式。

如何使这项工作成为可能,重点是让示例代码尽可能具有表现力?

编辑: 在Caleth的帮助下,我选择了Bolov的解决方案:

struct Symbol
{
    Symbol();
    explicit Symbol(const char*);

    template <class... Args> 
    static std::array<Symbol, sizeof...(Args)> Array(Args... args)
    {
        return {Symbol{args}...}; 
    } 
};

int main()
{
    auto symbols = Symbol::Array("a", "b", "c");
}

2 个答案:

答案 0 :(得分:4)

嗯,你的构造函数是显式的,所以你需要使用它:

Symbol symbols[] = {Symbol{"a"}, Symbol{"b"}, Symbol{"c"}};

gcc和clang都是复制/移动构造函数,因为C ++ 17是必需的行为所以没有性能开销。

如果你真的想保留构造函数explicit并且能够创建一个数组而不为每个元素明确说明它,那么你可以创建一个辅助函数:

template <class... Args,
          class Enable = std::enable_if_t<(... && std::is_same_v<Args, const char*>)>>
auto make_symbols(Args... args) -> std::array<Symbol, sizeof...(Args)>
{
    return {Symbol{args}...};
}

并像这样使用它:

auto symbols = make_symbols("a", "b", "c");

此外,移动/副本完全被删除。

make_symbols函数使用C ++ 17特性来检查参数类型。如果您需要先前标准版本(包括C ++ 11)的约束,请参阅此答案Restrict variadic template arguments。或者,根据您的需要,取消支票也是一种选择。

答案 1 :(得分:1)

到目前为止,我提出的最好的是:

std::vector<Symbol> symbols;
for(auto v: { "a", "b", "c"})
    symbols.emplace_back(v);