编译模板参数的时间比较

时间:2011-06-30 06:24:16

标签: c++ templates comparison

我有一个要求,如果作为模板参数之一传递的整数大于某个值,我应该使用特定的类。否则,我应该得到编译时错误...

类似于以下内容:

enum Time { Day, Week, Month };

template<Time t, int length>
class Timer
{
}

现在,我必须以这样的方式限制实例化Timer -

Timer<Day,8>Timer<Day,9>等应该有效,但lengthDay一起使用时不能少于8。

同样,与length一起使用时,Week不能小于10,等等......

有人可以帮我解决一下如何在编译时实现这一目标吗?

5 个答案:

答案 0 :(得分:7)

所有其他答案都用于元编程以检测条件,另一方面我会保持简单:

template<Time t, int length>
class Timer
{
    static_assert( (t == Day && length > 7) 
                 ||(t == Week && length > 10)
                 ||(t == Month && length > 99), "Invalid parameters"
};

如果不满足条件,编译器将触发断言,并且通过错误消息验证和/或查看该行非常简单。

使用SFINAE工具禁用该类型的版本也会产生相同的结果:代码将无法编译,但代价是使错误消息更加复杂:这意味着什么{{1不是一个类型?肯定是,它是Timer<Day,5>

的实例化

编辑:以上Timer<Time,int>在C ++ 0x中实现,在没有C ++ 0x的编译器中,您可以将static_assert实现为宏:

static_assert

这个简单的宏不接受字符串文字作为第二个参数,而是接受单个单词。用法是:

#define static_assert( cond, name ) typedef char sassert_##name[ (cond)? 1 : -1 ];

错误消息需要一些人工解析,因为编译器会抱怨(如果条件不满足)static_assert( sizeof(int)==4, InvalidIntegerSize ) ) 的大小为负。

答案 1 :(得分:6)

length >= 8的结果作为bool模板参数传递给帮助程序模板。仅为true提供专业化服务。话虽如此,这听起来像是家庭作业,所以我会把编码留给你。

干杯&amp;第h

答案 2 :(得分:3)

你可以这样做:

template<bool> 
struct rule;

template<> 
struct rule<true> {};

template<Time Tm, int Len>
struct constraint;

//Rule for Day     
template<int Len>
struct constraint<Day, Len> : rule<(Len>= 8)>
{};

template<Time Tm, int Len>
class Timer : constraint<Tm, Len>
{
   //your code
};

测试代码:

int main() {
        Timer<Day, 7> timer1; //error 
        Timer<Day, 8> timer2; //okay
        return 0;
}

在线演示:


同样,您可以将WeekMonth的规则添加为:

//Rule for Week
template<int Len>
struct constraint<Week, Len> : rule<(Len>= 10)>
{};

//Rule for Month
template<int Len>
struct constraint<Month, Len> : rule<(Len>= 100)>
{};

答案 3 :(得分:2)

这种验证的想法通常是将工作交给专门的助手类,你专门研究每种参数。

template <typename T, size_t V>
class Foo
{
  static_assert(helper<T,V>::value, "Wrong Parameters");
};

有两种方法可以执行验证:

// Require full specialization
template <typename T, size_t V> struct helper: std::false_type {};

template <>
struct helper<Bar,0>: std::true_type {};

template <>
struct helper<Bar,4>: std::true_type {};


// Property like
template <typename T, size_t V> struct helper: std::false_type {};

template <size_t V>
struct helper<Bar, V>: std::integral_constant<bool, V <= 8> {};

当然,那些假设C ++ 0x设施。在C ++ 03中,您必须自己提供简单的true_typefalse_typeintegral_constant类。

答案 4 :(得分:0)

enum Time { Day, Week, Month };
template<Time T> struct Length;
template<> struct Length<Day> { static const int value = 8 ; };
template<> struct Length<Week> { static const int value = 9; };
template<> struct Length<Month> { static const int value = 10; };

template<bool b> struct Limit;
template<> struct Limit<true> { typedef bool yes; };

#define COMPILE_ASSERT(V) typedef typename Limit<(V)>::yes checked

template<Time t, int length>
class Timer
{
  COMPILE_ASSERT(length >= Length<t>::value);
};

请参阅demo here