首页 > 解决方案 > 模板类中的模板构造函数

问题描述

我正在尝试通过将行和列定义为模板参数来实现 Matrix 类。此外,我将 Vector 视为共享其大部分代码的“降级”矩阵类。

我想使用初始化列表来初始化我的类,因为它以旧的 c 数组方式使用。

当试图根据矩阵或向量为类提供一个且只有一个构造函数时,问题就出现了,因此禁止在编译时将矩阵初始化器列表分配给向量,将向量初始化器列表分配给矩阵。我尝试过使用模板和 std::enable_if,但我无法完全理解编译器的奇怪错误消息。

我发布了说明问题的简化代码,清除了所有解决问题的试验。在评论中,我进一步解释了我正在尝试做的事情。任何人都可以知道如何做我需要的吗?

#include <initializer_list>     

template<int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    Matrix(std::initializer_list<T> initializers) { }//Do some stuff inside
    Matrix(std::initializer_list<std::initializer_list<T>> initializers) { }//Do some stuff inside
};

template<int R, typename T=int>
using Vector = Matrix<R, 1, T>;

int main()
{
    Matrix<3, 3> m = { {1, 2, 3},
                       {4, 5, 6},
                       {7, 8, 9} };

    Vector<3> v = {10, 20, 30};

    Matrix<3, 3> m1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//This must be avoided using templates in constructors or SFINAE 
    Vector<3> v1 = { {10, 20, 30} };//This must be avoided using templates in constructors or SFINAE

    return 0;   
}

另外,我使用相同的代码发布了一个 coliru 链接:http: //coliru.stacked-crooked.com/a/17b5e8c504c262d1

非常感谢您提前。

标签: c++templatessfinae

解决方案


使用 C++20,您可以使用requiresto 丢弃重载:

template <int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    Matrix(std::initializer_list<T> initializers) requires (C == 1)
    { /*..*/ }

    Matrix(std::initializer_list<std::initializer_list<T>> initializers) requires (C != 1)
    { /*..*/ }
};

演示

在此之前,专业化:

template <int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    Matrix(std::initializer_list<std::initializer_list<T>> initializers)
    { /*..*/ }
};

template <int R, typename T>
struct Matrix<R, 1, T>
{
    T data[R][1];

    Matrix(std::initializer_list<T> initializers)
    { /*..*/ }
};

或者可以使用 SFINAE:

template <int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    template <typename D = C, std::enable_if_t<D == 1, int> = 0>
    Matrix(std::initializer_list<T> initializers)
    { /*..*/ }

    template <typename D = C, std::enable_if_t<D != 1, int> = 0>
    Matrix(std::initializer_list<std::initializer_list<T>> initializers)
    { /*..*/ }
};

推荐阅读