2017-06-30 75 views
1

我有一個類可以接收相同類型的可變參數模板。每種類型有一個嵌套的值,它應該是唯一的:靜態斷言可變參數模板的嵌套值是唯一的

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

「的C++ 0x」是不是真的* *的事情,這只是對C++ 11在使用名稱。 –

+0

是的我不確定這個:/但我的目標平臺之一需要用-std = C++編譯0x –

+1

這是一個不完整的C++ 11支持的指標,所以如果你去C++ 11路由。例如,流的移動語義可能不起作用。 –

回答

2

就可以解決這個問題遞歸:

鑑於類型( T1,T2,T3,...,Tn)

  1. T1::value != T2::value必須是真實的
  2. T1::value != Ti::value必須是真實的,對於i = 3,...,N
  3. T2::value != Ti::value必須是真實的I = 3,...,N

在代碼,你可以做這樣的:

#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, ":("); 
} 
2

希望別人能展現出更優雅和簡單的解決方案,我提出了一個static_assert()的插入在TypeMe和d在一組特定(allDifferentEnums)和泛型(allDiffsfistDiffs)類型特徵的支持下開發。

下面是一個簡單的,但編譯例如

#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; 
} 
+0

將無法​​工作,謝謝這樣做,但@MadScientist答案更短,我對它的理解也更少 –

相關問題