Я не знаю, если вы все еще заинтересованы, но ... чтобы ответить на ваш первоначальный вопрос ... если вы измените порядок аргументов шаблона для contain
... Я имею в виду
if( contains<foo, ????>() )
вместо
if( contains<????, foo>() )
ваш contains
(переименован в containsFB
в моих следующих примерах) может быть, начиная с C ++ 14, простой constexpr
функцией
template <foobar F0, foobar ... Fs>
constexpr bool containsFB ()
{
using unused = bool[];
bool ret { false };
(void)unused { false, ret |= F0 == Fs ... };
return ret;
}
Начиная с C ++ 17, вы также можете использовать свертывание шаблонов, и constantFB
можно записать как черты типа, которые наследуются от std::true_type
или std::false_type
.
template <foobar F0, foobar ... Fs>
struct containsFB : public std::integral_constant<bool, ((F0 == Fs) || ...)>
{ };
Ниже приведено полноерабочий C ++ 14 пример
#include <iostream>
#include <utility>
enum foobar { foo, bar, baz };
template <foobar F0, foobar ... Fs>
constexpr bool containsFB ()
{
using unused = bool[];
bool ret { false };
(void)unused { false, ret |= F0 == Fs ... };
return ret;
}
/* C++17 alternative
template <foobar F0, foobar ... Fs>
struct containsFB : public std::integral_constant<bool, ((F0 == Fs) || ...)>
{ };
*/
template <foobar ... Fs>
void f ()
{
if( containsFB<foo, Fs...>() ) std::cout << "foo!";
if( containsFB<bar, Fs...>() ) std::cout << "bar!";
if( containsFB<baz, Fs...>() ) std::cout << "baz!";
}
int main ()
{
f<foo,bar>();
}
Если вы хотите сделать containsFB
(функцию или структуру) немного более универсальным, вы можете шаблонизировать тип значений;так что
template <typename T, T F0, T ... Fs>
вместо
template <foobar F0, foobar ... Fs>