c++ - 根据可变参数模板对类型进行分类

标签 c++ c++11 templates variadic-templates template-meta-programming

我最近看了一个视频,启发了我编写自己的神经网络系统,我希望网络中的节点数量可以调整。

起初我通过解析节点数数组在运行时实现了这一点,但我想知道我是否可以在编译时这样做。这是我希望完成的事情的示例。

template<int FirstNodes, int SecondNodes, int... OtherNodes>
class Net
{
    tuple<Eigen::Matrix<float, FirstNodes, SecondNodes>, ...> m_weights;
    // More matricies with the values from the OtherNodes
};

作为更详细的示例,Net<784, 16, 16, 10> n; n.m_weight 应该有类型

tuple<Eigen::Matrix<float, 784, 16>,
    Eigen::Matrix<float, 16, 16>,
    Eigen::Matrix<float, 16, 10>>

根据我对 C++ 和 constexpr 的了解,这应该是可能的。

我应该补充一点,我能够做到

template<int FirstNodes, int SecondNodes, int... OtherNodes>
class Net
{
public:
    Net()
    {
        auto nodes = {FirstNodes, SecondNodes, OtherNodes...};

        auto i = nodes.begin();
        do 
        {
            // Eigen::Matrix<float, Dynamic, Dynamic>
            Eigen::MatrixXf m(*(i++), *i);
        } while (i+1 != nodes.end());
    }
};

但后来我只是再次使用动态矩阵,这不是我所希望的。

任何建议或工作示例将不胜感激。

最佳答案

您需要某种类型转换,给定一个 N 整数列表,返回一个 N - 1 矩阵的 tuple。这是一个 C++17 解决方案:

template <int A, int B, int... Is>
auto make_matrix_tuple()
{   
    if constexpr(sizeof...(Is) == 0)
    {
        return std::tuple<Eigen::Matrix<float, A, B>>{};
    }
    else
    {
        return std::tuple_cat(make_matrix_tuple<A, B>(), 
                            make_matrix_tuple<B, Is...>());
    }
}

live example on wandbox


在 C++11 中,您可以递归地实现这种类型转换:

template <int... Is>
struct matrix_tuple_helper;

template <int A, int B, int... Rest>
struct matrix_tuple_helper<A, B, Rest...>
{
    using curr_matrix = Eigen::Matrix<float, A, B>;
    using type = 
        decltype(
            std::tuple_cat(
                std::tuple<curr_matrix>{},
                typename matrix_tuple_helper<B, Rest...>::type{}
            )
        );
};

template <int A, int B>
struct matrix_tuple_helper<A, B>
{
    using curr_matrix = Eigen::Matrix<float, A, B>;
    using type = std::tuple<curr_matrix>;
};

template <int... Is>
using matrix_tuple = typename matrix_tuple_helper<Is...>::type;

C++14 方法:

struct matrix_tuple_maker
{
    template <int A, int B, int C, int... Is>
    static auto get()
    {
        return std::tuple_cat(get<A, B>(), get<B, C, Is...>());
    }

    template <int A, int B>
    static auto get()
    {
        return std::tuple<Eigen::Matrix<float, A, B>>{};
    }
};

static_assert(std::is_same_v<
    decltype(matrix_tuple_maker::get<784, 16, 16, 10>()),
    std::tuple<Eigen::Matrix<float, 784, 16>,
               Eigen::Matrix<float, 16, 16>,
               Eigen::Matrix<float, 16, 10>>
    >);

关于c++ - 根据可变参数模板对类型进行分类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46989948/

相关文章:

c++ - C++中分配的大小限制?

c++ - 如何使函数接受任意数量的参数而不使用 f(...)?

c++ - Macports GCC 4.8 无法链接 OSX Lion 上的 c++ 库

c++ - OpenGL 拾取 - 射线/球体相交错误

c++ - 矩阵重载

c++ - 关于调用 srand 的说明

c++ - Std::stoul 在 C++ 中失败后未被捕获

c++ - 未知模板类型的默认值或零值

C++ - 前向声明和别名(使用 using 或 typedef)

c++ - C++中模板选择的优先级