抱歉,这个浮夸的名字,我想创建一个constexpr
函数,该函数接受可变数量的boolean模板参数,并以C语言返回第一个true
值的“模板索引” ++ 11(仅C ++ 14解决方案受欢迎,但将不被视为答案)。
例如,调用此函数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?),这应该可行。
#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
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;
}
constexpr
函数。因此,我以递归方式重写了它,以使C ++ 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...);
}
这将使用函数语法而不是模板进行调用,并且由于将template参数增加,因此将始终为constexpr
。