在 CRTP 中使用嵌套名称说明符

Using a nested name specifier in CRTP

我正在使用 CRPT,需要访问在派生 class 中定义的基 class 中的参数。它在成员函数中使用时有效,但在(我猜)编译时表达式中无效(问题发生在定义类型时)。下面的代码说明了这个问题:

#include <iostream>
#include <array>

template <typename impl_t>
struct base {
// no complaints
  void print () {
    std::cout << "Base, impl_t::i_q = " << impl_t::i_q << std::endl;
  }
// compiler error:
//                 clang++: no member named 'i_q' in 'deriv_t'
//                 g++:     incomplete type ‘deriv_t’ used in nested name specifier
  using vec_t = std::array<double, impl_t::i_q>;
};

struct deriv_t : public base<deriv_t> {
  static const std::size_t i_q = 1;
};

int main () {
  deriv_t d;
  d.print();
}

我只是想知道这里违反了什么规则?我想出的解决方案是在模板中定义 i_qimpl_t,但想知道是否有更整洁的方法来解决问题。

解决方案:

感谢 Evg,这里是解决方案:

template <typename impl_t>
struct traits;

template <typename impl_t>
struct base_t {
  void print () {
    std::cout << "Base, impl_t::i_q = " << traits<impl_t>::i_q << std::endl;
  }
  using vec_t = std::array<double, traits<impl_t>::i_q>;
};

struct deriv_t;

template <>
struct traits<deriv_t> {
  static const std::size_t i_q = 1;
};
struct deriv_t : public base_t<deriv_t> {
};

impl_tbase 中的不完整类型。您可以使用另一个模板参数或使用类型特征技术来解决问题:

template<class>
struct traits;

template<>
struct traits<deriv_t>
{
    static constexpr std::size_t i_q = 1;
};

...

void print () {
    std::cout << "Base, i_q = " << traits<impl_t>::i_q << std::endl;
}

using vec_t = std::array<double, traits<impl_t>::i_q>;

您在 print() 中没有抱怨,因为在其实例化时 impl_t 成为一个完整类型。