2015-10-01 1 views
4

Извините за помпезное название, я хотел бы создать constexpr функции, которая принимает переменное число логических аргументов шаблона и возвращает «индекс шаблона» первого true значения в C++ 11 (C++ 14 только решения приветствуются, но не принимаются в качестве ответа).VARIADIC constexpr

Например, вызов этой функции Selector

Selector< false, false >() == 0 // none of the template argument is true 
Selector< true, false, true >() == 1 // first true template argument is the first one 
Selector< false, false, true, false >() == 3 // .. and here it's the third one 

Типичное использование этого, и причина, почему я называю это «тип-селектор», будет

Selector< std::is_pointer<T>::value, std::is_arithmetic<T>::value >() 

и причина почему я хотел бы, чтобы он был constexpr для использования в частичной специализированной специализации.

Я не совсем уверен, как это сделать, хотя я думаю, что с использованием вариативных шаблонов, специализированной специализации constexpr (для случая 0) и рекурсии (возможно ли «потреблять» аргументы шаблона, например shift в bash?), это должно быть выполнимо.

+0

Downvote пожалуйста объяснить ... – Sheljohn

+0

Это хороший вопрос. Но ему не хватает усилий ... –

+0

@KarolyHorvath Согласен, я сейчас пытаюсь что-то придумать. – Sheljohn

ответ

2

на основе ответа по @CoffeeandCode, вот еще один пример, который работает, как ожидалось, используя constexpr рекурсии:

#include <iostream> 
#include <cstddef> 

template<bool B0=false, bool... Bs> 
constexpr std::size_t Selector(std::size_t I = 1) 
{ 
    return B0 ? I : Selector<Bs...>(I+1); 
} 

template<> 
constexpr std::size_t Selector<false>(std::size_t I) 
{ 
    return 0; 
} 

int main() 
{ 
    std::cout<< Selector() << std::endl; 
    std::cout<< Selector<false,false>() << std::endl; 
    std::cout<< Selector<true,false,true>() << std::endl; 
    std::cout<< Selector<false,false,true,false>() << std::endl; 
} 
6
#include <cstddef> 
#include <type_traits> 

template <std::size_t I, bool... Bs> 
struct selector; 

template <std::size_t I, bool... Bs> 
struct selector<I, true, Bs...> : std::integral_constant<std::size_t, I> {}; 

template <std::size_t I, bool... Bs> 
struct selector<I, false, Bs...> : selector<I+1, Bs...> {}; 

template <std::size_t I> 
struct selector<I> : std::integral_constant<std::size_t, 0> {}; 

template <bool... Bs> 
constexpr std::size_t Selector() 
{ 
    return selector<1, Bs...>::value; 
} 

DEMO

+1

Это красиво :) – Sheljohn

1

Я не был удовлетворен тем, что ответ не был чисто constexpr функции. Так что я переписал его в рекурсии, что соответствует компилятор С ++ 11 будет принимать:

#include <cstddef> 

template<std::size_t I = 1> 
constexpr std::size_t selector(bool value = false){ 
    return value ? I : 0; 
} 

template<std::size_t I = 1, typename ... Bools> 
constexpr std::size_t selector(bool first, bool second, Bools ... others){ 
    return first ? I : selector<I+1>(second, others...); 
} 

Это можно было бы назвать с функциональным синтаксисом, а не шаблоны, и всегда будет constexpr из-за параметра шаблона приращения.

+0

Немного другой синтаксис, а типы ввода не ограничиваются 'bool', но это тоже работает :) – Sheljohn

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

  • Нет связанных вопросов^_^