可变变量constexpr类型选择器

问题描述 投票:4回答:3

抱歉,这个浮夸的名字,我想创建一个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?),这应该可行。

c++ c++11 templates variadic-templates constexpr
3个回答
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

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; }


1
投票
我不满意答案不是纯粹的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
© www.soinside.com 2019 - 2024. All rights reserved.