模板类的实例化对象上的 C++ 模板元函数

标签 c++ templates boost metaprogramming boost-mpl

我希望这个问题不会过于复杂。我意识到元编程作用于类型而不是这些类型的对象;但是,我仍在尝试通过 1) 从类中检索类型信息,然后 2) 在该类型信息上使用元函数来获得相同的结果。

对我的情况的解释如下,并附有简化的代码摘录:

我有一个矩阵模板类,我称之为 Matrix_Base。与 Eigen 采取的方法有些相似,我允许矩阵大小有两种可能性——要么在编译时固定,要么在运行时固定。 Matrix_Base 的简化声明是:

template <typename Type, uint32_t rows_ = 1, uint32_t cols_ = 1,>
class Matrix_Base{
/* 
...
*/
};

运行时大小的矩阵由参数 0 表示。

检查矩阵的运行时与编译时大小相当简单(使用 boost::mpl):

            typedef typename mpl::if_<
                typename mpl::or_<
                typename mpl::equal_to<
                typename mpl::int_<rows_>::type,
                mpl::int_<0>
                >::type,
                typename mpl::equal_to <
                typename mpl::int_<cols_>::type,
                mpl::int_<0>
                >
                >::type,
                mpl::true_,
                mpl::false_
                >::type runtime_size_type;

这已经过测试并且工作正常。我的麻烦从这里开始......

目前,我正在以下列方式使用上面的 boost::mpl 代码:

namespace internal {
template <uint32_t rows = 1, uint32_t cols_ = 1>
struct Runtime_Size_Helper {
typedef typename mpl::if_< 
// REST OF THE BOOST::MPL code here //
>::type runtime_size_t
bool value() { return runtime_size_t::value;}
};
} // namespace
template <typename Type, uint32_t rows_ = 1, uint32_t cols_ = 1>
class Matrix_Base{
// ...
static constexpr uint32_t rows = rows_;
static constexpr uint32_t cols = cols_;
bool is_runtime_sized;
// ...
};

template <typename T, uint32_t R, uint32_t C>
bool Matrix_Base<T,R,C>::is_runtime_sized = internal::Runtime_Size_Helper<R,C>::value();

这使得该 mpl 函数的结果成为 Matrix_Base 类的成员。到目前为止一切顺利。

我想使用某种间接形式,通过将实例化对象传递给 runtime_size_type 来确定它的值。根据示例代码,确定这一点所需的唯一信息是 col 和 row 的 uint32_t 参数。

对于实例化的Matrix_Base对象,相关信息永远不会从它的compile-type值中改变。矩阵的大小将是不可变的;大小将从模板参数设置,或者——对于运行时大小的矩阵——通过构造函数设置。在这两种情况下,模板参数都是固定的并且是类型信息的一部分。我将此信息保存为类中的静态变量,我什至尝试添加一个带有所有模板参数的 typedef 作为 my_type typename typename Matrix_Base<T,rows_, cols_, ...> my_type但我似乎无法弄清楚如何编写一个元函数,我可以向其传递一个 Matrix_Base 对象(显然作为引用或指针)并重新提取相关信息。

如果它们能提供必要的功能,我完全愿意合并(其他)boost 库。

希望这是清楚的。请让我知道这里是否有不清楚的地方或者只是愚蠢的地方。

最好的问候, 什穆尔

编辑了文本以使问题更加清晰

最佳答案

做你想做的事情的最快方法(你并没有真正详细说明)是让你的矩阵类模板继承自存储类模板,并根据你的 MPL 谓词是否专门化存储类返回真或假

#include <array>
#include <iostream>
#include <vector>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/comparison.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/logical.hpp>

using namespace boost;

// in C++98, use 
// template<int R, int C>
// struct is_runtime_sized: mpl::if<
// ...
// >::type {};
template<int R, int C>
using is_runtime_sized = typename mpl::if_<
    mpl::or_<
        mpl::equal_to<mpl::int_<R>, mpl::int_<0>>,
        mpl::equal_to<mpl::int_<C>, mpl::int_<0>>
    >,
    mpl::true_, mpl::false_
>::type;

请注意,我已经删除了一些不必要的 typename 事件,以使 MPL 谓词更具可读性。

template<class T, int R, int C, bool = is_runtime_sized<R, C>::value>
struct MatrixStorage
{
    MatrixStorage() = default;
    MatrixStorage(int r, int c): data_(r * c) {} // zero-initializes
protected:    
    std::vector<T> data_;
};

template<class T, int R, int C>
struct MatrixStorage<T, R, C, false>
{
    MatrixStorage() = default;
    MatrixStorage(int, int): data_{} {} // zero-initializes
protected:    
    std::array<T, R * C> data_;    
};

在这里,我拆分了动态和静态存储矩阵的实现。前者使用 std::vector,后者使用 std:array。与 Eigen 类似,两者都有一个默认构造函数,并且都有一个采用零初始化的矩阵维度的构造函数。

template<class T, int R = 0, int C = 0>
struct Matrix: public MatrixStorage<T, R, C>
{
    Matrix() = default;
    // In C++98, write:
    // Matrix(int r, int c): MatrixStorage<T, R, C>(r, c) {}
    using MatrixStorage<T, R, C>::MatrixStorage;
    int size() const { return this->data_.size(); }
};

实际的 Matrix 类继承自 MatrixStorage,并根据当前存储的数据返回一个 size()

int main()
{
    Matrix<int> m_dyn(3, 3);
    std::cout << m_dyn.size() << "\n"; // 9

    Matrix<int, 2, 2> m_stat;
    std::cout << m_stat.size() << "\n"; // 4
}

Live Example .如您所见,动态分配的矩阵大小为 9,静态大小的矩阵大小为 4。请注意,上面的代码中有两个小的 C++11 功能,如果需要,您可以轻松解决使用 C++11。

关于模板类的实例化对象上的 C++ 模板元函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19346677/

相关文章:

c++ - is_invocable_r 忽略返回参数

c++ - 为什么我不能有模板和默认参数?

c++ - 将未命名节点添加到 boost::property_tree::ptree

c++ - 多线程中对象的行为

c++ - 为什么我的 C++ 代码计算整数的最大值和最小值是错误的?

c++ - 预处理后解析 C++ 源文件

c++ - 如何加快这个盒子堆叠变化?

c++ - 包含 unique_ptr 的 unordered_map 的对象的深拷贝

c++ - `std::common_type` 是关联的吗?

c++ - boost lexical_cast <int> 检查