Clang 错误 "implicit instantiation of undefined template std::tuple_size<auto>"

Clang error "implicit instantiation of undefined template std::tuple_size<auto>"

Clang 的行为“undefined template smthg”是否有(干净的)解决方法?

代码示例:

额外的见解:

我期望的是,根据上面提供的示例,分别获得两种类型 - evaluatable - std::tuple_size_v :

class std::tuple<
   struct std::integral_constant<bool,0>,
   struct std::integral_constant<bool,1>,
   struct std::integral_constant<bool,0>
>
class std::tuple<bool,bool,bool>

我漏掉了一点吗?

代码示例:

#include <tuple>
#include <array>
#include <type_traits>

template <template <typename> class trait, typename... Ts>
struct trait_result {

    template <template <typename...> class T>
    using as_t = T<typename trait<Ts>::type...>;
    template <template <typename...> class T>
    constexpr static auto as_v = T{trait<Ts>::value...};
    using as_tuple_t = as_t<std::tuple>;
    constexpr static auto as_tuple_v = std::tuple{trait<Ts>::value...};
};

namespace test
{
    template <typename T>
    using is_int = std::is_same<int, T>;
    using results = trait_result<is_int, char, int, bool>;

    using results_as_tuple = results::as_t<std::tuple>; // ok
    using results_as_tuple_value_type = std::decay_t<decltype(results::as_v<std::tuple>)>; // ko

    static_assert(std::tuple_size_v<results_as_tuple> == std::tuple_size_v<results_as_tuple_value_type>);
}
template <template <typename...> class T>
constexpr static auto as_v = T{trait<Ts>::value...};

这尝试使用T的演绎指南来生成类型。

如果你写

auto as_v = results::as_v<std::tuple>;

编译器崩溃,甚至在您完成其余工作之前。

假设你愿意没有推导指南:

template <template <typename...> class T>
constexpr static T<decltype(trait<Ts>::value)...> as_v = {trait<Ts>::value...};

编译其余代码。

现在,

template <template <typename...> class T>
constexpr static auto as_v = T<decltype(trait<Ts>::value)...>{trait<Ts>::value...};

键入时也不会编译

auto as_v = results::as_v<std::tuple>;

所以问题可能不是演绎指南,而是constexpr static auto这里。

这在class之外:

template<template<class...>class T, template<class>class trait, class...Ts>
constexpr auto foo = T{trait<Ts>::value...};

加上 class:

template <template <typename...> class T>
constexpr static decltype(foo<T, trait, Ts...>) as_v = foo<T, trait, Ts...>;

为您提供演绎指南并且没有内部编译器错误。

感谢 @Yakk - Adam Nevraumont,作为结论,这是我修复它的方法:

using as_array_t = std::array<std::tuple_element_t<0, decltype(std::tuple{trait<Ts>::value...})>, sizeof...(Ts)>;
constexpr static inline auto as_array_v = as_array_t{trait<Ts>::value...};

这避免了代码库中的另一个#if __clang__ /* workaround on clang ICE ... */

[编辑] 出于完整性目的:

  • 即使上面的代码修复了 Clang 的编译,它也没有用于 Clang-CL。下面的代码仍然编译失败,同样的错误信息。
template <typename T>
using is_int = std::is_same<int, T>;
using results = trait_result<is_int, char, int, bool>;

using results_as_tuple = results::as_t<std::tuple>;
using results_as_tuple_value_type = std::decay_t<decltype(results::as_v<std::tuple>)>; // error here