我有一个类的模板(我们称之为 A),它应该是其他类(B 或 C)之一的子类,具体取决于我的自定义特征结构中的编译时间条件。我附上了一个重现行为的片段。

#include <type_traits>

template<typename T>
class cls_template {
public:
  using method_arg_type = T;
  virtual void method(method_arg_type) = 0;
};

using A = cls_template<float>;
using B = cls_template<int>;

template<typename T>
struct traits {
  using cls = std::conditional<std::is_floating_point<T>::value, A, B>;
};

//class C : public traits<float>::cls {
class C : public A {
public:
  virtual void method(method_arg_type arg) {};
};

int main() {
  A *a = new C();
}

如果我这样保留(将 A 硬编码为父类(super class)),则一切正常。但是,一旦我用注释掉的行替换了类定义,我就会收到以下错误消息:
test.cpp:21:27: error: unknown type name 'method_arg_type'
  virtual void method(method_arg_type arg) {};
                      ^
test.cpp:25:10: error: cannot initialize a variable of type 'A *'
  (aka 'cls_template<float> *') with an rvalue of type 'C *'
  A *a = new C();
     ^   ~~~~~~~

为什么 method_arg_type 不再定义?为什么 C 不再被识别为 A 的子类?我发现如果 traits 不是模板(如果我只是将类型硬编码到结构中),则一切正常。

最佳答案

您正在尝试从 traits<float>::cls 类型的 std::conditional<std::is_floating_point<T>::value, A, B> 派生。它既不是 A 也不是 B ,它是 conditional 模板的特化。要么从它的 ::type 派生,它会按你的预期工作,要么使用 conditional_t (C++14)。

class C : public traits<float>::cls::type { // ok
                                   ^^^^^^
public:
  virtual void method(method_arg_type arg) {};
};

demo
template<typename T>
struct traits {
  using cls = std::conditional_t<std::is_floating_point<T>::value, A, B>;
                              ^^
  // above is C++14, in C++11 you'd have to write
  // using cls = typename std::conditional<std::is_floating_point<T>::value, A, B>::type;
};

class C : public traits<float>::cls { // also ok
public:
  virtual void method(method_arg_type arg) {};
};

demo

关于c++ - 如何对由特征选择的父类(super class)进行子类化?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40535707/

10-16 05:15