【问题标题】:CRTP and template template?CRTP和模板模板?
【发布时间】:2012-08-13 05:11:56
【问题描述】:

我想做模板类的CRTP,我想让抽象基类知道派生类的模板参数。

我试过了,但它不起作用:

template<template<class T, unsigned int TDIM> class TCRTP> class NAbstract
{
    T _data[TDIM];
};

template<typename T, unsigned int TDIM> class NArray : NAbstract< NArray<T, TDIM> >
{

};

template<typename T, unsigned int TDIM> class NVector : NAbstract< NVector<T, TDIM> >
{

};

g++ 4.6.2 告诉我:

main.cpp|5|error: 'T' does not name a type|
main.cpp|8|error: type/value mismatch at argument 1 in template parameter list for 'template<template<class T, unsigned int TDIM> class TCRTP> class NAbstract'|
main.cpp|8|error:   expected a class template, got 'NArray<T, TDIM>'|
main.cpp|13|error: type/value mismatch at argument 1 in template parameter list for 'template<template<class T, unsigned int TDIM> class TCRTP> class NAbstract'|
main.cpp|13|error:   expected a class template, got 'NVector<T, TDIM>'|

什么是问题,对于这样的事情有什么好的解决方案?

【问题讨论】:

标签: c++ templates crtp template-templates


【解决方案1】:

一种解决方案是部分专门化模板:

template <typename> struct NAbstract;

template <typename T, unsigned int N>
struct NAbstract<NArray<T, N>>
{
    T _data[N];
    // ...
};

或者:

template <template <typename, unsigned int> class Container,
          typename T, unsigned int N>
struct NAbstract<Container<T, N>>
{
    T _data[N];
    // ...
};

【讨论】:

  • 在我的例子中,CRTP 的兴趣在于我将能够在 NAbstract 类中为所有派生类型定义类似 200 个函数。如果我专门化模板,CRTP 的优势就消失了(但也许我错了,我没有理解你的例子)。
  • @Vincent:好的,我正在添加一个稍微不同的偏特化,它可能会更有效。
【解决方案2】:

下面是修复错误后的代码:

template<class T, unsigned int TDIM, template<class, unsigned int> class TCRTP>
class NAbstract
{
  T _data[TDIM];
};

template<typename T, unsigned int TDIM>
class NArray : NAbstract< T, TDIM, NArray >
{
};

template<typename T, unsigned int TDIM>
class NVector : NAbstract< T, TDIM, NVector >
{
};

您不能使用template template 参数。事实上,编译器只是忽略了它们。
例如在您的原始代码中,TTDIM 在下面的行中被忽略:

template<template<class T, unsigned int TDIM> class TCRTP> class NAbstract
                       ^^^              ^^^^  // <--- ignored

【讨论】:

  • 独立传递TTDIM 是不必要的错误的来源。但是,传递不带模板参数的派生类是个好主意。
【解决方案3】:

你可以通过特质来实现这一点。那么,NAbstract 就不需要模板模板参数了。

template<class TCRTP>
class NAbstract {
    typename TCRTP::value_type data_[TCRTP::DIM];
};

template<typename T, unsigned int TDIM>
struct NTraits {
    typedef T value_type;
    enum { DIM = TDIM };
};

template<typename T, unsigned int TDIM>
struct NArray : NAbstract< NTraits<T, TDIM> > {
};

template<typename T, unsigned int TDIM>
struct NVector : NAbstract< NTraits<T, TDIM> > {
};

【讨论】:

  • 此代码产生以下错误:(使用 g++ 4.6.2):错误:在 'class NArray' 中没有名为 'value_type' 的类型(当我声明一个 NArray)
  • @Vincent:我的错。 NVector 直到该行代码之后才能公开其特征。使用固定版本进行编辑,但有用性取决于您想要从 NAbstract 中得到什么。
猜你喜欢
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
相关资源
最近更新 更多