2013-07-06 2 views
1

Я пытался использовать шаблоны variadics для тестирования некоторых propierties (type_trait) во время компиляции, но, кажется, следующий код не может скомпилироватьC++ 11 constexpr VARIADIC логика выражения

template<typename test> 
constexpr bool trait_test(){ 
    return test::value; 
} 

template<typename test, typename... Others> 
constexpr bool trait_test(){ 
    return test::value&&trait_test<Others...>(); 
} 

template<typename A, typename... Deriveds> 
constexpr bool commonBaseClass{ 
    return trait_test<std::is_base_of<A,Deriveds>...>(); 
} 

Проблема, как представляется, что, когда «Другие» имеет длину от 0 есть 2 возможных вызовы

trait_test<typename test> 
trait_test<typename test, typename... Others={}> 

и компилятор не знает, которым один выглядывать. Я хочу, конечно, заглянуть первым (и сохранить все constexpr)

+1

В следующий раз включите в свой вопрос http://sscce.org. Это значительно упрощает проверку вашего кода другими. – Xeo

ответ

3

Минимальное изменение, чтобы получить код компиляция будет заменить вторую test_trait перегрузки с:

template<typename T0, typename T1, typename... Others> 
constexpr bool trait_test(){ 
    return T0::value&&trait_test<T1, Others...>(); 
} 

, что означает 1 аргумент только совпадает с первым, и 2 или более соответствуют второму.

+0

mmm T0 не оценивается, поэтому мне нужно пройти фиктивный тип, но если я это сделаю, когда я позвоню , это приведет к: T1 :: value && T1 :: value, поэтому T1 будет оцениваться дважды. В этом случае это нормально, потому что False && False = False и TRue && True = True, но не применимо к другим случаям (например, если && заменяется на «xor»). Поскольку если A xor 1 = 1, то A xor 1 xor 1 = 0. Также неприменимо в большинстве случаев с генератором без «constexpr». – GameDeveloper

+1

@darioOO typo fixed. – Yakk

+0

Следует принять этот ответ теперь, другой ответ не компилируется на VS 2013 поэтому этот «более портативный». – GameDeveloper

2

Действительно, это неоднозначно. Шаблон функции, принимающий один аргумент шаблона, не является более специализированным, чем шаблон функции, принимающий 1 или более аргументов шаблона, поскольку частичный порядок шаблонов функций выполняется по аргументам - и оба шаблона функций имеют нулевые аргументы функции.

Если я могу предложить альтернативный подход:

#include <type_traits> 

template<typename... Ts> 
struct all_of; 

template<typename T> 
struct all_of<T> : std::integral_constant<bool, T::value> { }; 

template<typename T, typename... Ts> 
struct all_of<T, Ts...> : std::integral_constant<bool, 
    T::value && all_of<Ts...>::value> { }; 

template<typename A, typename... Deriveds> 
constexpr bool commonBaseClass() 
{ 
    return all_of<std::is_base_of<A, Deriveds>...>(); 
} 

Вы бы затем использовать commonBaseClass() таким образом:

struct X { }; 
struct Y : X { }; 
struct Z : X { }; 

int main() 
{ 
    static_assert(commonBaseClass<X, Y, Z>(), "!"); 
} 

Вот является live example.

+0

черт возьми, я должен глубоко понять эту интегральную константу, второй раз, когда я это вижу .. Спасибо, что она работает! – GameDeveloper

+2

@ DarioOO: Добро пожаловать. Да, 'integ_constant' - это не самая интуитивная вещь, но на самом деле даже не сложно получить интуицию для нее, если вы немного поиграете с ней. Это, в основном, структура со статическим элементом данных 'значение' типа интегральной константы (например,' integ_constant 'сводится к' struct X {static constexpr bool value = V; /*...s some other helpful. .. * /} '(см. [здесь] (http://en.cppreference.com/w/cpp/types/integral_constant) для ссылки) –

Смежные вопросы