根据模板参数启用Template Ctor

时间:2015-01-12 12:18:54

标签: c++ templates c++11

我有一个简单的CRTP模板类,我一直在玩这个类,我得到了一个点,我需要拥有相同的ctor,但在构造函数初始化列表中基本上做了不同的事情。

我确实有另一种解决方案,但我想知道我想做的事情能否以更好的方式实现。

下面粘贴了该类的精简版。 你可以忽略Eigen的东西它只是一个矩阵库。

template<class ImplT, size_t N, bool SquareMatrix = false>
class Foo
{
  template<bool Test, typename Then, typename Else>
  using conditional_t = typename std::conditional<Test, Then, Else>::type;

  // this is defined at compile time so no need to init it
  using VecN = Eigen::Matrix<double, N, 1>;

  // this is a dynamic matrix so dimensions need to be specified at runtime
  using MatN = Eigen::MatrixXd;
  using MatrixType = conditional_t<SquarePreCovariance, MatN, VecN>;

  inline ImplT& impl() noexcept             { return static_cast<ImplT&>(*this); }
  inline const ImplT& impl() const noexcept { return static_cast<const ImplT&>(*this); }

  public:
  // if SquareMatrix == false
  Foo()
    : parameters3(Matrix(N, N))
  {}

  // if SquareMatrix == true
  Foo()
    : parameters2(Matrix(N, N)), 
      parameters3(Matrix(N, N)),
    {}

  // easy solution that covers all cases
  Foo()
    : parameters3(Matrix(N, N)), 
  {
    if (SquareMatrix)
        parameters2.resize(N,N);
  }

private:
  VecN parameters;
  MatrixType parameters2;
  MatN  parameters3;
};

2 个答案:

答案 0 :(得分:11)

有条件地委派构造函数怎么样?

private:

    // if SquareMatrix == false
    Foo(std::false_type)
      : parameters3(Matrix(N, N))
    {}

    // if SquareMatrix == true
    Foo(std::true_type)
      : parameters2(Matrix(N, N)), 
        parameters3(Matrix(N, N))
      {}

public:

    Foo() : Foo(std::integral_constant<bool, SquareMatrix>{})  {}

答案 1 :(得分:7)

构造函数可以是模板化的,只要可以推导出所有模板参数或具有默认值。

模板参数的替换失败导致在重载解析期间跳过它。

必须注意明确两个构造函数版本是有效的重载,并且附加的虚拟模板参数可以解决这个问题。

#include <utility>
#include <iostream>

template <bool B>
struct S {
  template <bool B_ = B, typename = typename std::enable_if<!B_>::type>
  S() { std::cout << "1" << std::endl; }

  template <bool B_ = B, typename = typename std::enable_if<B_>::type, typename = void>
  S() { std::cout << "2" << std::endl; }
};

int main() {
  S<false> sf; // okay, prints 1
  S<true> st; // okay, prints 2
}