0%

One_of implementation in variadic template

不得不說,這真的是個炫技,不過還真有用。
原先的程式碼,煩譟又容易錯

1
2
if (thing.x == 1 || thing.x == 2 || thing.x == 3)
dosomething();

可以改寫成這樣
C++11版

1
2
3
4
5
6
7
8
9
template<typename U, typename ... T>
bool one_of(U&& u, T && ... t)
{
bool match = false;
(void)std::initializer_list<bool>{ (match = match || u == t)... };
return match;
}
if (one_of(thing.x, 1, 2, 3))
dosomething();

關劍在Varadic Template Pack expansion,他創造了一個initial_list,其值就是當下match的值。
將initial_list的值印出來更容易看出變化,因此小小變化一下

1
2
3
4
5
6
7
8
9
template<typename U, typename ... T>
bool one_of(U&& u, T && ... t)
{
bool match = false;
auto list = std::initializer_list<bool>{ (match = match || u == t)... };
for (auto v : list)
std::cout << v << std::endl;
return match;
}

部過我們的inital_list根本沒用到, 所以就直接宣告成void讓編譯氣決定最佳化了
C++17版可以寫得更簡單

1
2
3
4
5
template<typename U, typename ... T>
bool one_of(U&& u, T && ... t)
{
return ( (u == t) || ... );
}

Reference

Parameter pack
C++17 Fold Expressions
A Data Point for MSVC vs Clang Code Generation