This:
if constexpr((has_foo<T>() && ...))
{
(T().foo(), ...);
}
проверяет, есть ли каждые T
foo()
, а затем вызывает foo()
на каждые T
.
То, что вы, очевидно, хотите, для каждого T
, условно вызвать его. Вы можете сделать это, обернув это в лямбду для указанного c типа:
auto maybe_foo = [](auto x){
if constexpr (has_foo<decltype(x)>()) {
x.foo();
}
};
И затем вызывать эту лямбду для каждого типа:
(maybe_foo(T()), ...);
Это самое простое решение, наверное. Недостатком является то, что вы создаете кучу T()
с, даже если вы не можете .foo()
их. Вы можете обойти это, заключив T
s в тип тега:
template <typename T> struct type_t { using type = T; };
auto maybe_foo = [](auto x){
using T = typename decltype(x)::type;
if constexpr (has_foo<T>()) {
T().foo();
}
};
(maybe_foo(type_t<T>()), ...);
Отдельно от всего этого используйте идиому обнаружения в C ++ 17 вместо того, чтобы использовать свою собственную версию. Это будет намного проще:
template <typename T> using foo_type_t = decltype(std::declval<T>().foo());
template <typename T> using has_foo = is_detected<foo_type_t, T>;