C++14 で static_if 書いてみた

上げるの忘れてた。 generic lambda を使っていい感じに static_if を書いてみました。

ソース

#include <iostream>


template<typename Then, typename Else>
auto
static_if(std::integral_constant<bool, true>, Then then, Else else_){
    return then;
}


template<typename Then, typename Else>
auto
static_if(std::integral_constant<bool, false>, Then then, Else else_){
    return else_;
}


template<bool Cond, typename Then, typename Else>
auto
static_if(Then then, Else else_){
    return static_if(std::integral_constant<bool, Cond>{}, then, else_);
}


template<bool Cond, typename Then>
auto
static_if(Then then){
    return static_if<Cond>(then, [](...){});
}



#include <boost/type_traits/has_plus.hpp>

template<typename T>
auto
twice(T t){
    static_if<boost::has_plus<T, T>::value>(
        [](auto t){
            std::cout << t + t << std::endl;
        },
        [](...){
            std::cout << "Error" << std::endl;
        }
    )(t);
}


template<int N>
int
test(){
    return static_if<(N > 0)>(
        [](auto n){
            return N + test<decltype(n){}-1>();
        },
        [](...){
            return N;
        }
    )(std::integral_constant<int, N>{});
}


int
main(){
    twice(10);
    twice(std::string("homu"));
    twice("homu");

    std::cout << test<5>() << std::endl;


    return 0;
}

出力結果

20
homuhomu
Error
15

then 節のコードを generic lambda で書き、参照した値を generic lambda 経由で使用することで偽の場合でもコンパイルエラーにならないようにしています。 ただ、型を使用したい場合は引数値として渡してやる必要があるのでちょっと手間ではあります。 それでもだいぶすっきりと書けるのではないかな。