我有一个要求,如果作为模板参数之一传递的整数大于某个值,我应该使用特定的类。否则,我应该得到编译时错误...
类似于以下内容:
enum Time { Day, Week, Month };
template<Time t, int length>
class Timer
{
}
现在,我必须以这样的方式限制实例化Timer
-
Timer<Day,8>
,Timer<Day,9>
等应该有效,但length
与Day
一起使用时不能少于8。
同样,与length
一起使用时,Week
不能小于10,等等......
有人可以帮我解决一下如何在编译时实现这一目标吗?
答案 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;
}
在线演示:
Timer<Day, 7> timer1
:已评论)Timer<Day, 7> timer1
:未评论)同样,您可以将Week
和Month
的规则添加为:
//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_type
,false_type
和integral_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。