【问题标题】:Initializing array through explicit constructor通过显式构造函数初始化数组
【发布时间】:2018-07-22 09:39:32
【问题描述】:

我正在编写一个具有显式构造函数的类,该构造函数采用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");
}

【问题讨论】:

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


    【解决方案1】:

    好吧,你的构造函数是显式的,所以你需要这样使用它:

    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。或者,根据您的需要,也可以选择删除支票。

    【讨论】:

    • 我知道我应该提到明显的解决方案......这不是很好的扩展。
    • 你说的“它不能很好地扩展”是什么意思?
    • 对于每个变量,你必须重复类名。这使得它不如我希望的那样简洁。
    • @bgp2000 构造函数explicit吗?
    • 我不相信您需要在这里检查参数。任何传递非符号的东西都无法实例化模板。 template &lt;class... Args&gt; std::array&lt;Symbol, sizeof...(Args)&gt; make_symbols(Args... args) { return {Symbol{args}...}; }
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2017-06-23
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多