模板参数的编译时间比较

Compile time comparison of template parameter

本文关键字:时间 比较 编译 参数      更新时间:2023-10-16

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

它类似于以下内容:

enum Time { Day, Week, Month };
template<Time t, int length>
class Timer
{
}

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

Timer<Day,8>Timer<Day,9>等应该工作,但与Day一起使用时,length不能小于8。

类似地,当与Week等一起使用时,length不能小于10…

有人能帮助我了解如何在编译时实现这一点吗?

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

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

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

使用SFINAE工具禁用该类型的版本也会获得相同的结果:代码不会编译,但代价是使错误消息的读取更加复杂:Timer<Day,5>不是类型意味着什么?当然是,它是Timer<Time,int>的实例化

EDIT:上面的static_assert是在C++0x中实现的,在没有C++0x的编译器中,您可以将static_assert实现为宏:

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

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

static_assert( sizeof(int)==4, InvalidIntegerSize ) )

错误消息需要一些人工解析,因为编译器会抱怨(如果条件不满足(sassert_InvalidIntegerSize的大小为负数。

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

干杯&hth。

您可以这样做:

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

在线演示:

  • http://www.ideone.com/tSBhG(Timer<Day, 7> timer1:已发表评论(
  • http://www.ideone.com/mbN6m(Timer<Day, 7> timer1:未发表评论(

类似地,您可以将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)>
{};

这种验证的想法通常是将工作交给一个专用的助手类,您可以为每种参数专门化该助手类。

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类。

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

请参阅此处的演示。