【问题标题】:A compile-type template predicate compiles with Clang, but not with GCC or MSVC编译类型的模板谓词使用 Clang 编译,但不能使用 GCC 或 MSVC 【发布时间】:2023-03-21 15:20:01 【问题描述】:
考虑以下 C++ 代码:
#include <type_traits>
template<int x, int y, bool visible>
struct Point { };
template<typename T>
struct Predicate : std::false_type { };
template<typename... Types, Types... Values, template<Types...> class Head>
struct Predicate<Head<Values...>> : std::true_type { };
static_assert(Predicate<Point<1, 2, true>>::value, "assert");
template <class... Types> // Types is a template type parameter pack
class Tuple; // but not a pack expansion
template <class T, int... Dims> // Dims is a non-type template parameter pack
struct multi_array; // but not a pack expansion
template <class... T>
struct value_holder {
template <T... Values> struct apply { }; // Values is a non-type template parameter pack
}; // and a pack expansion
template <class... T, T... Values> // error: Values expands template type parameter
struct static_array; // pack T within the same template parameter list
— 结束示例 ]
【讨论】:
【解决方案2】:
似乎模板参数在这种情况下是不可推导出的。
您可能想尝试使用函数参数,似乎推导规则更容易使用它们。
类似这样,如果您需要将输出作为类型,您可以将其包装在结构中:
#include <type_traits>
template<int x, int y, bool visible>
struct Point { };
template <typename T>
struct NoPoint { };
template <typename T>
constexpr auto Match(T &&)
{
return false;
}
template<template < auto ... > typename Head, auto ... Values>
constexpr auto Match(Head<Values...> &&)
{
return true;
}
static_assert(Match(Point<1, 2, true>{}), "I am a wombat.");
static_assert(Match(NoPoint<int>{}), "I am also a wombat.");
#include <type_traits>
#include <utility>
template<int x, int y, bool visible>
struct Point { };
template <typename T>
struct NoPoint { };
template <typename T>
constexpr auto Match(T) -> std::false_type;
template<template < auto ... > typename Head, auto ... Values>
constexpr auto Match(Head<Values...>) -> std::true_type;
template <typename T>
struct Predicate : decltype(Match(std::declval<T>())) {};
static_assert(Predicate<Point<1, 2, true>>::value, "I am a wombat.");
static_assert(Predicate<NoPoint<int>>::value, "I am not a wombat.");
//Test types
template<int x, int y, bool visible>
struct Point { };
template <typename T>
struct NoPoint { };
//Test Cases
static_assert(Predicate_v<Point<1, 2, true>>, "I am a wombat.");
static_assert(Predicate_v<NoPoint<int>>, "I am not a wombat.");