如何在没有标准库的情况下在 C++ 中为 braced-init-list 创建构造函数?

How to create constructor for braced-init-list in c++ without standard library?

我希望能够使用大括号初始化列表来初始化我的对象:

#include <initializer_list>
 
template <class T>
struct S {
    T v[5];
    S(std::initializer_list<T> l) {
      int ind = 0;
      for (auto &&i: l){ 
        v[ind] = i; 
        ind++;
        }
    }
};
 
int main()
{
    S<int> s = {1, 2, 3, 4, 5}; 
}

正如我在这里发现的:https://en.cppreference.com/w/cpp/utility/initializer_list,有必要为此使用标准库。

但这对我来说很奇怪。我建议这种初始化是 C++ 语法的一部分。

是否可以在不使用 std:initializer_list 的情况下创建构造函数?

编辑:

它对于标准库不可用的嵌入式设备编程很有用(例如 Arduino AVR)。

作为一种变通方法,可以做类似

的事情
#include <iostream>

template <class T>
struct S {
    T v[5];

    template<typename... Args>
    requires (std::same_as<T, Args> && ...)
    S(Args... args) {
        static_assert(sizeof...(args) <= 5);
        int ind = 0;
        ((v[ind++] = args), ...);
    }
};
 
int main()
{
    S<int> s = {1, 2, 3, 4, 5}; 

    for ( auto e : s.v ) {
        std::cout << e << ' ';
    }
}

live on godbolt

正如 RemyLebeau 在评论中指出的那样,需要一个像 S(T,T,T,T,T) 这样的构造函数。使用可变构造函数模板和 C++17 折叠表达式,您可以让编译器为每个参数数量提供该形式的构造函数。

请注意,如果您想要 class 中的其他构造函数,requires 约束 (C++20) 很重要。它以 S(T,T,T,...) 形式约束模板,并且不会参与参数的重载决议,这些参数并非都是 T 类型。也应该可以通过 std::enable_if*.

实现 C++20 之前的版本

另请记住,编译器将为每个具有不同数量参数的调用实例化一个具有匹配签名的构造函数。因此,如果经常使用并且大括号中有许多不同数量的参数,这可能会导致代码膨胀。


* 例如这样:

template<typename... Args,
    typename std::enable_if_t<(std::is_same_v<T, Args> && ...), bool> = true>
S(Args... args) {
    //...
}