我有一个类,它接收相同类型的可变参数模板。每种类型都有一个独特的嵌套值:
template <SomeEnum _se, int _val>
struct Pack
{
enum {val_se = _se};
enum {val = _val};
};
int main()
{
TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<C_SE, 3>> tm_abc; // OK
TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<A_SE, 3>> tm_aba; // Should fail (first and last Pack are templated with A_SE)
(void)tm_abc;
(void)tm_aba;
return (0);
}
整个测试代码:
#include <cstdio>
template <typename ... ArgPacks>
class TypeMe
{
public:
TypeMe();
private:
template <typename ... APs>
void cycleAPs();
template <typename AP>
void cycleAP();
};
template <typename ... ArgPacks>
TypeMe<ArgPacks...>::TypeMe()
{
// Maybe the static assertion should go here
cycleAPs<ArgPacks...>();
}
template <typename ... ArgPacks>
template <typename ... APs>
void TypeMe<ArgPacks...>::cycleAPs()
{
int _[] = {0, (cycleAP<APs>(), 0)...};
(void)_;
return ;
}
template <typename ... ArgPacks>
template <typename AP>
void TypeMe<ArgPacks...>::cycleAP()
{
printf("SomeEnum = %d, Val = %d\n", static_cast<int>(AP::val_se), AP::val);
return ;
}
enum SomeEnum
{
A_SE,
B_SE,
C_SE,
MAX
};
template <SomeEnum _se, int _val>
struct Pack
{
enum {val_se = _se};
enum {val = _val};
};
int main()
{
TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<C_SE, 3>> tm_abc; // OK
TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<A_SE, 3>> tm_aba; // Should fail (first and last Pack are templated with A_SE)
(void)tm_abc;
(void)tm_aba;
return (0);
}
在C ++ 0x中,有没有办法在编译时检查每个Pack :: val_se是不同的?还是用C ++ 11?
感谢您阅读
修改:
相同的代码,但@MadScientist回答,谢谢
#include <cstdio>
template <typename ...Ts>
struct are_mutually_different;
template <typename T>
struct are_mutually_different<T>
{
static const bool value = true;
};
template <typename T1, typename T2, typename ...Ts>
struct are_mutually_different<T1, T2, Ts...>
{
static const bool value = (T1::val_se != T2::val_se) &&
are_mutually_different<T1, Ts...>::value &&
are_mutually_different<T2, Ts...>::value;
};
template <typename ... ArgPacks>
class TypeMe
{
public:
TypeMe();
private:
template <typename ... APs>
void cycleAPs();
template <typename AP>
void cycleAP();
};
template <typename ... ArgPacks>
TypeMe<ArgPacks...>::TypeMe()
{
static_assert(are_mutually_different<ArgPacks...>::value, "!"); // <3
// Maybe the static assertion should go here
cycleAPs<ArgPacks...>();
}
template <typename ... ArgPacks>
template <typename ... APs>
void TypeMe<ArgPacks...>::cycleAPs()
{
int _[] = {0, (cycleAP<APs>(), 0)...};
(void)_;
return ;
}
template <typename ... ArgPacks>
template <typename AP>
void TypeMe<ArgPacks...>::cycleAP()
{
printf("SomeEnum = %d, Val = %d\n", static_cast<int>(AP::val_se), AP::val);
return ;
}
enum SomeEnum
{
A_SE,
B_SE,
C_SE,
MAX
};
template <SomeEnum _se, int _val>
struct Pack
{
enum {val_se = _se};
enum {val = _val};
};
int main()
{
TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<C_SE, 3>> tm_abc; // OK
// TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<A_SE, 3>> tm_aba; // Should fail (first and last Pack are templated with A_SE)
(void)tm_abc;
// (void)tm_aba;
return (0);
}
答案 0 :(得分:2)
您可以递归地解决此问题:
给出类型(T1,T2,T3,......,Tn)
T1::value != T2::value
必须是真的T1::value != Ti::value
必须为true
对于i = 3,...,n T2::value != Ti::value
必须为true
醇>
在代码中,您可以这样做:
#include <type_traits>
template <typename ...Ts>
struct are_mutually_different;
template <typename T>
struct are_mutually_different<T>
{
static const bool value = true;
};
template <typename T1, typename T2, typename ...Ts>
struct are_mutually_different<T1, T2, Ts...>
{
static const bool value = (T1::value != T2::value) &&
are_mutually_different<T1, Ts...>::value &&
are_mutually_different<T2, Ts...>::value;
};
void test()
{
using _1 = std::integral_constant<int, 1>;
using _2 = std::integral_constant<int, 2>;
using _3 = std::integral_constant<int, 3>;
using _4 = std::integral_constant<int, 4>;
using _5 = std::integral_constant<int, 5>;
static_assert(are_mutually_different<_1, _2, _3, _4>::value, ":(");
static_assert(!are_mutually_different<_1, _1, _3, _4>::value, ":(");
static_assert(!are_mutually_different<_1, _2, _1, _4>::value, ":(");
static_assert(!are_mutually_different<_1, _2, _3, _2>::value, ":(");
}
答案 1 :(得分:2)
希望其他人可以展示更优雅,更简单的解决方案,我建议在static_assert()
中插入TypeMe
,并在一组特定(allDifferentEnums
的支持下进行开发)和泛型(allDiffs
和fistDiffs
)类型特征。
以下是一个简化但可编译的例子
#include <type_traits>
enum SomeEnum
{ A_SE, B_SE, C_SE, MAX };
template <SomeEnum _se, int _val>
struct Pack
{ };
template <typename T, T ... ts>
struct firstDiffs;
template <typename T, T t>
struct firstDiffs<T, t> : std::true_type
{ };
template <typename T, T t, T ... ts>
struct firstDiffs<T, t, t, ts...> : std::false_type
{ };
template <typename T, T t, T t0, T ... ts>
struct firstDiffs<T, t, t0, ts...> : firstDiffs<T, t, ts...>
{ };
template <typename T, T ... ts>
struct allDiffs;
template <typename T>
struct allDiffs<T> : std::true_type
{ };
template <typename T, T t, T ... ts>
struct allDiffs<T, t, ts...>
: std::integral_constant<bool, firstDiffs<T, t, ts...>::value &&
allDiffs<T, ts...>::value>
{ };
template <typename...>
struct allDifferentEnums: std::false_type
{ };
template <SomeEnum ... ses, int ... vals>
struct allDifferentEnums<Pack<ses, vals>...> : allDiffs<SomeEnum, ses...>
{ };
template <typename ... ArgPacks>
class TypeMe
{ static_assert(allDifferentEnums<ArgPacks...>::value, "!"); };
int main()
{
// OK
TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<C_SE, 3>> tm_abc;
// static_assert failed "!"
// TypeMe<Pack<A_SE, 1>, Pack<B_SE, 2>, Pack<A_SE, 3>> tm_aba;
(void)tm_abc;
// (void)tm_aba;
}