在编译时检测 std::tuple 中的类型包含

Emi*_*äck 3 c++ c++20

我的目标是编写一个函数:

  1. 在编译时可调用
  2. 接受一个Tuple表示任意 std::tuple的模板参数
  3. 接受一个Match表示要测试的类型的模板参数
  4. 如果元组有 1 个以上匹配类型的元素,则返回 true

我在 GCC 10.2 上,如果需要,我可以升级。我也可以切换到 Clang。我避免使用 Boost,但也开始觉得将其包含在我的项目中是不可避免的。

如果 C++20 允许idx变量作为编译时常量,我就完成了。但是,这并没有使其成为标准:

template<typename Tuple, typename Match>
consteval bool tuple_holds()
{
    constexpr std::size_t size = std::tuple_size<Tuple>::value;
    constexpr auto all = std::ranges::iota_view{std::size_t{0}, size};

    for (const auto idx : all) {
        // This doesn't work, as idx is not available as a compile-time constant
        using Type = std::tuple_element<idx, Tuple>::type;

        if (std::is_same<Type, Match>::value) {
            return true;
        }
    }

    return false;
}


using A = std::tuple<float, int>;


int main()
{
    static_assert(tuple_holds<A, int>());
    static_assert(tuple_holds<A, float>());
}
Run Code Online (Sandbox Code Playgroud)

我怀疑答案在于 SFINAE,但我不确定如何更进一步。

Hol*_*Cat 8

你不需要花哨的 C++20 特性来做到这一点。

template <typename, typename>
struct tuple_holds {};

template <typename ...A, typename B>
struct tuple_holds<std::tuple<A...>, B>
    : std::bool_constant<(std::is_same_v<A, B> || ...)>
{};
Run Code Online (Sandbox Code Playgroud)

用法:tuple_holds<std::tuple<A, B>, C>::value