Variadic constexpr类型选择器

时间:2015-10-01 10:38:14

标签: c++ c++11 variadic-templates constexpr

很抱歉这个浮夸的名字,我想创建一个<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="one">I am one</div>函数,它接受可变数量的布尔模板参数,并返回第一个{模板索引“{ {1}}值,在C ++ 11中(C ++ 14只有解决方案欢迎,但不会被接受为答案)。

例如,调用此函数constexpr

true

这个的典型用法,以及我称之为“类型选择器”的原因是

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 的原因是用于部分模板专业化。

我不确定如何解决这个问题,虽然我认为使用可变参数模板,constexpr模板特化(对于0情况)和递归(可以“使用”模板参数,如{{1在bash中?),这应该是可行的。

3 个答案:

答案 0 :(得分: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 :(得分: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;
}

答案 2 :(得分: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...);
}

这将使用函数语法而不是模板调用,并且因为模板参数递增而始终为constexpr