具有初始化列表的结构模板和构造函数

Struct template and constructor with initializer list

我试图更好地理解模板,为此我制作了一个教育结构:

template<typename T, size_t N>
struct SVectorN
{
    SVectorN(const T(&another)[N]);
private:
    T components[N];
};

我创建的构造函数允许我创建一个实例,如下所示:

double input[4] = { 0.1, 0.2, 0.3, 0.4 };
SVectorN<double, 4> t(input);

但我不知道如何支持这样的初始化:

SVectorN<double, 4> c = { 1.3, 1.4, 1.5, 1.6 };

或者像这样更好:

SVectorN c(1.3, 1.4, 1.5, 1.6 ); // SVectorN<double, 4>

有可能还是我完全遗漏了什么?

谢谢

这两种方法都是可行的,C++ 中的初始化很棘手,原因很简单,因为有很多方法,而且它们之间存在细微差别。

我会推荐这样的东西:

#include <cstdint>
#include <utility>

template <typename T, std::size_t N> struct SVectorN {
    SVectorN(const T (&another)[N]);

    template <typename First, typename Second, typename... Tail>
    SVectorN(First &&f, Second &&s, Tail &&...t)
        : components{std::forward<First>(f), std::forward<Second>(s),
                     std::forward<Tail>(t)...} {}

  private:
    T components[N];
};

int main() {
    double input[4] = {0.1, 0.2, 0.3, 0.4};
    SVectorN<double, 4> t(input);

    SVectorN<double, 4> c = {1.3, 1.4, 1.5, 1.6};
    SVectorN<double, 4> d{1.3, 1.4, 1.5, 1.6};
    SVectorN<double, 4> e(1.3, 1.4, 1.5, 1.6);
}

我必须明确强制在可变参数 ctor 中存在至少两个参数,否则它会更好地匹配 t 的构造并且会失败。

如果 std::initializer_list 没有 ctor,

c,d,e 实际上是相同的初始化。没有,因为用一个初始化数组不容易完成。

现在,如果您想自动推导模板参数,这要归功于 CTAD。为了简化 link,您只需向编译器指定如何从构造函数的参数中推断出 class 的模板参数。

例如:

template <class T, std::size_t N>
explicit SVectorN(const T (&)[N]) -> SVectorN<T, N>;
template <typename F, typename S, typename... Tail>
SVectorN(F &&, S &&, Tail &&...) -> SVectorN<F, sizeof...(Tail) + 2>;

将允许:

    SVectorN tx(input);
    SVectorN cx = {1.3, 1.4, 1.5, 1.6};
    SVectorN dx{1.3, 1.4, 1.5, 1.6};
    SVectorN ex(1.3, 1.4, 1.5, 1.6);

我真的很喜欢@Quimby 的回答,但我不确定它是否适用于一个论点。或者,您可以使用 std::initializer_listvariadic 重载构造函数。现阶段效率不是很高,但您可以根据需要进行优化。

#include <iostream>

template <typename T, size_t N>
struct SVectorN
{
    private:
        T components[N];
    
    public:
        SVectorN(const T(&another)[N])
        {
            std::copy(std::begin(another), std::end(another), components);
        }
    
        SVectorN(std::initializer_list<T> &&init_)
        {
            std::copy(std::begin(init_), std::end(init_), components);
        }
    
        template <typename ... U>
        SVectorN(U ...val_)
        {
            T tmp[] = { val_ ... };
            std::copy(std::begin(tmp), std::end(tmp), components);
        }
    
        void print() const
        {
            for (auto &&c : components)
                std::cout<< c <<",";
            std::cout<<std::endl;
        }
};

int main()
{
    double input[4] = { 0.1, 0.2, 0.3, 0.4 };
    
    SVectorN<double, 4> t(input);
    t.print();
    
    SVectorN<double, 4> c = { 1.3, 1.4, 1.5, 1.6 };
    c.print();
    
    SVectorN<double, 4> d(1.3, 1.4, 1.5, 1.6 );
    d.print();
}

结果是:

0.1,0.2,0.3,0.4,
1.3,1.4,1.5,1.6,
1.3,1.4,1.5,1.6,

在线代码:https://rextester.com/MIF22368