将结构作为模板参数传递 - 如何修复此代码?

时间:2010-09-24 21:19:05

标签: c++ visual-c++ templates parameters struct

我正在尝试在VC2010下编译以下代码。

struct CircValRange
{
    double a,b; // range: [a,b)
};

template <struct CircValRange* Range>
class CircVal
{
    // todo
};


const CircValRange SignedDegRange= {-180., 180.};

CircVal<SignedDegRange> x;

我正在

error C2970: 'CircVal' : template parameter 'Range' : 'SignedDegRange' : an expression involving objects with internal linkage cannot be used as a non-type argument
1>          d:\4\circval\circval\circval.h(8) : see declaration of 'CircVal'
1>          d:\4\circval\circval\circval.h(13) : see declaration of 'SignedDegRange'

我正在尝试定义一个模板化的类CircVal,它将接收一个struct Range作为模板化参数。

我不希望能够将具有一个范围的类分配给具有另一个范围的类(我希望它们是不同的类型)。

我该怎么做?

4 个答案:

答案 0 :(得分:6)

有人推荐了一个构造函数参数,我是第二个。但你仍然可以按照原来的要求去做

struct CircValRange
{
    double a,b; // range: [a,b)
};

template <CircValRange const& Range>
class CircVal
{
    // todo
};


extern const CircValRange SignedDegRange= {-180., 180.};

CircVal<SignedDegRange> x;

但请注意,确定CircVal<SignedDegRange>的类型标识的属性不是 SignedDegRange的值,而是地址 / identity它的。也就是说,以下内容不起作用,因为CircVal<SignedDegRange1>表示不同的类型

extern const CircValRange SignedDegRange1 = {-180., 180.};

CircVal<SignedDegRange1> y = x; // error!

因此,枚举可能更适合此

enum RangeKind {
  SignedDegRange,
  UnsignedDegRange
};

const CircValRange Ranges[] = { { -180., -180. }, { 0., 360. } };

template <RangeKind Range>
class CircVal
{
    // todo
};

甚至是具有静态成员函数的traits类,类似于其他人拥有的解决方案

template <typename Range>
class CircVal
{
    // todo
};

struct SignedDegRange {
  static double min() { return -180.; }
  static double max() { return  180.; }
};

CircVal<SignedDegRange> x;

答案 1 :(得分:4)

为什么不将范围作为构造函数参数?

,而不是将其作为模板?

struct CircValRange
{
    double a,b; // range: [a,b)
};

class CircVal
{
public:
    CircVal(const CircValRange &_range) : range(_range) {}
private:
    CircValRange range;
    // todo
};


const CircValRange SignedDegRange= {-180., 180.};

CircVal x(SignedDegRange);

这样,CircVal的每个实例都会有一个相关的范围。然后,您可以覆盖赋值操作符以防止使用不同的值进行赋值。

或者,如果您对模板采用不同的方式感兴趣,可以对范围执行类似的操作:

template <int MIN, int MAX>
class range {
  static const int min = MIN, max = MAX;
};
template <class T>
class CircVal {
  //todo
};

CircVal< range<10,20> > x;

但当然,这不是很干净或可用。

答案 2 :(得分:1)

template <class Range>
class CircVal
{
    // todo
};

template <class Range> class CircVal;
template<>
class CircVal<CircValRange> {...

实例化

CircVal<CircValRange> ...

答案 3 :(得分:1)

我认为你省略了一步。如果你想创建一个可以专注于类型的模板CircVal,你可以写:

template<typename Range>
class CircVal
{
   ...
};

如果您想在CircValRange上专门化它,可以在代码中进一步创建它的实例。

你似乎尝试并强制执行的是它只接受从某个基类派生的类,但不幸的是,这不是模板的工作方式 - 你必须找到另一种强制执行的方法,可能是通过鸭子打字