开发者

Passing a structure as a template-parameter - How can I fix this code?

I'm trying to compile the following code under VC2010.

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

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


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

CircVal<SignedDegRange> x;

I'm getting

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 o开发者_Python百科f 'CircVal'
1>          d:\4\circval\circval\circval.h(13) : see declaration of 'SignedDegRange'

I am trying to define a templated class CircVal that will receive a struct Range as the templated parameter.

I don't want it to be possible to assign classes with one range to classes with another range (I want them to be different types).

How can I do it?


Someone has recommended a constructor parameter, which I second. But you can still do it as originally desired

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

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


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

CircVal<SignedDegRange> x;

But notice that the property that determines the type-identity of CircVal<SignedDegRange> is not the value of SignedDegRange, but the address/identity of it. That is, the following does not work because CircVal<SignedDegRange1> denotes a different type

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

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

As such, an enumeration may be better suited for this

enum RangeKind {
  SignedDegRange,
  UnsignedDegRange
};

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

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

Or even a traits class with static member functions, similar to a solution someone else had

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

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

CircVal<SignedDegRange> x;


Instead of making it a template, why don't you reqire a range as a constructor parameter?


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);

That way each instance of a CircVal will have an associated range. Then you can override the assignment opearator to prevent assignment with different values.

Or, if you're interested in a different way with templates, you could do something like this for a range:

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;

But of course, that's not very clean or usable.


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

or

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

to instantiate

CircVal<CircValRange> ...


I think you are omitting one step. If you want to create a template CircVal that you can specialise on a type, you write:

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

and if you then want to specialise it on CircValRange, you create an instance of it as you do further down in your code.

What you seem to try and enforce is that it'll only accept classes derived from a certain base class but unfortunately that's not quite the way templates work - you'll have to find another way to enforce that, maybe by duck typing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜