简体   繁体   中英

Struct template and constructor with initializer list

I'm trying to better understand templates and for this purpose I made an educational struct:

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

Constructor that I made allows me to make an instance, like this:

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

But I can't figure out how to support initializating like this:

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

Or even better something like this:

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

Is it possible or am I missing something comepletely?

Thanks

Both approaches are possible, initialization in C++ is tricky simply because of how many ways there are and their subtle differences.

I would recommend something like this:

#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);
}

I had to explicitly enforce presence of at least two arguments in the variadic ctor, otherwise it would be a better overload match for t 's construction and that would fail.

c,d,e are practically the same initialization if there is not ctor with std::initializer_list . Which there is not because initializing an array with one cannot be easily done.

Now, if you want to automatically deduce the template parameters, that is possible thanks to CTAD . To simplify that link, you have to just specify to the compiler how to deduce class's template arguments from a constructor's arguments.

For example the following:

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>;

will allow:

    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);

I really like the answer from @Quimby, but I'm not sure if it would work with one argument. Alternatively, you could overload the constructors with std::initializer_list and variadic . It's not very efficient at this stage, but you can optimize it as per your needs.

#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();
}

Results are:

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

Online code: https://rextester.com/MIF22368

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM