将intializer列表聚合inialization转发给std::array成员。

问题描述 投票:1回答:1

我有一个类,封装了一个stl兼容的容器类型,它是唯一的类成员,并给出了很多向量数学函数,可以应用在这个向量上。

这个类有各种各样的构造函数,其中一个构造函数是接受一个初始化器列表。

template <class Type, class VectorType = std::vector<Type>>
class MathVector
{
public:
    using initializer_list = std::initializer_list<Type>;

    MathVector (initializer_list il) : vector(il) {}

    // many more constructors and member functions here

private:
    VectorType vector:
}

当一些像 MathVector<int> foo = { 1, 2, 3 } 运作良好。MathVector<int, std::array<int, 3>> bar = { 1, 2, 3 } 在clang上编译失败,出现了类似于

(86, 55) No matching constructor for initialization of 'std::__1::array<int, 3>'

std::vector<int> foo = { 1, 2, 3 }std::array<int, 3> bar = { 1, 2, 3 } 工作,所以我想,尽管语法相同。std::array 在这种情况下,并不是真正的通过初始化列表来构造的。当我查看std库源时,这种猜测变得更加强烈,因为我没有发现任何基于初始化列表的 std::array 构造函数。此外, cppreference 告诉我 它可以被初始化为 聚合初始化 - 这似乎不是任何一种通常的构造函数。那么有没有办法为我的类创建一个构造函数,正确地将一个初始化的语法转发到一个叫做 std::array 成员?

c++ c++14 initializer-list stdarray
1个回答
1
投票

与标签调度。

template <typename T>
struct type_identity { using type = T; };

template <typename Type, typename VectorType = std::vector<Type>>
class MathVector
{
public:
    MathVector(std::initializer_list<Type> il)
        : MathVector(il, type_identity<VectorType>{}) {}

private:
    template <typename T>
    MathVector(std::initializer_list<Type> il, type_identity<T>)
        : vector(il) {}

    template <typename T, std::size_t N>
    MathVector(std::initializer_list<Type> il, type_identity<std::array<T, N>>)
        : MathVector(il, std::make_index_sequence<N>{}) {}

    template <std::size_t... Is>
    MathVector(std::initializer_list<Type> il, std::index_sequence<Is...>)
        : vector{ *(il.begin() + Is)... } {}

    VectorType vector;
};

DEMO


另一种解决方案是使用可变模板构造函数。

template <typename Type, typename VectorType = std::vector<Type>>
class MathVector
{
public:
    template <typename... Ts>
    MathVector(Ts&&... ts)
        : vector{ std::forward<Ts>(ts)... } {}

    MathVector(MathVector& rhs)
        : MathVector(const_cast<const MathVector&>(rhs)) {}

    MathVector(const MathVector& rhs)
        : vector(rhs.vector) {}

private:
    VectorType vector;
};

DEMO 2

或更短的 :

template <typename Type, typename VectorType = std::vector<Type>>
class MathVector
{
public:
    MathVector(std::convertible_to<Type> auto&&... ts)
        : vector{ std::forward<decltype(ts)>(ts)... } {}

private:
    VectorType vector;
};

DEMO 3

© www.soinside.com 2019 - 2024. All rights reserved.