デッド コードの除去は、一般的な最適化です。
ただし、コンパイラが最適化を行うことをまったく信頼していない場合は、静的 iftemplate
ライブラリを作成できます。
かなり恐ろしいハックの束を読みたくない場合は、オチまで飛ばしてください。
#include <utility>
#include <type_traits>
template<bool b>
struct static_if_t {
static_if_t( static_if_t const& ) = default;
static_if_t() = default;
static_if_t( static_if_t<b>(*)(std::integral_constant<bool,b>) ) {}
};
template<bool dead>
struct static_if_branch {};
template<bool b>
struct static_else_if_t {
static_else_if_t( static_else_if_t const& ) = default;
static_else_if_t() = default;
static_else_if_t( static_else_if_t<b>(*)(std::integral_constant<bool,b>) ) {}
};
template<bool b>
static_if_t<b> static_if(std::integral_constant<bool,b> unused=std::integral_constant<bool,b>()) {return {};}
template<bool b>
static_else_if_t<b> static_else_if(std::integral_constant<bool,b> unused=std::integral_constant<bool,b>()) {return {};}
static auto static_else = static_else_if<true>;
template<typename Lambda, typename=typename std::enable_if< std::is_same< decltype(std::declval<Lambda&&>()()), decltype(std::declval<Lambda&&>()()) >::value >::type>
static_if_branch<true> operator*( static_if_t<true>, Lambda&& closure )
{
std::forward<Lambda>(closure)();
return {};
}
template<typename Lambda, typename=typename std::enable_if< std::is_same< decltype(std::declval<Lambda&&>()()), decltype(std::declval<Lambda&&>()()) >::value >::type>
static_if_branch<false> operator*( static_if_t<false>, Lambda&& /*closure*/ )
{
return {};
}
template<typename Unused>
static_if_branch<true> operator*( static_if_branch<true>, Unused&& ) {
return {};
}
static_if_t< true > operator*( static_if_branch<false>, static_else_if_t<true> ) {
return {};
}
static_if_t< false > operator*( static_if_branch<false>, static_else_if_t<false> ) {
return {};
}
そして、ここにオチがあります:
#include <iostream>
int main() {
static_if<true>* [&]{
std::cout << "hello\n";
} *static_else* [&]{
std::cout << "doom\n";
};
static_if<false>* [&]{
std::cout << "doom the\n";
} *static_else* [&]{
std::cout << "world\n";
};
static_if<false>* [&]{
std::cout << "fello\n";
} *static_else_if<false>* [&]{
std::cout << "yellow\n";
} *static_else_if<false>* [&]{
std::cout << "hehe\n";
};
static_if( std::is_same<int, int>() )* [&]{
std::cout << "int is int\n";
};
static_if( std::is_same<double, double>() )* [&]{
std::cout << "double is double\n";
} *static_else_if( std::is_same<int, double>() )* [&]{
std::cout << "int is double\n";
} *static_else* [&]{
std::cout << "sky is not blue\n";
};
}
しかし、なぜそれをしたいのですか? 実際の例
(上記には 2 つの構文があることに注意してくださいstatic_if
-- onestatic_if<compile time boolean expression>
と another static_if( std::is_whatever<blah>() )
)。
さて、上記は完全に正気ではありませんが、上記の手法を使用すると、選択されたブランチに基づいて異なる型を許可するコンパイル時の三項演算子を作成できます。これはきちんとしています。
つまり、次のようなものです。
auto result = trinary<std::is_same<A,B>::value>% 7 | 3.14;
の型はresult
、int
とA
がB
同じ型で、double
異なる場合です。あるいは:
auto result = meta_trinary<std::is_same<A,B>::value>% [&]{return 7;} | [&]{return 3.14;};
必要に応じて、コードのブロック全体を条件付きで評価し、戻り値の条件付きの型を格納できるようにします。