C++ 如何检查函数中的模板参数是否与给定类型别名的专门化匹配
我有以下代码:C++ 如何检查函数中的模板参数是否与给定类型别名的专门化匹配,c++,templates,variadic-templates,c++17,type-alias,C++,Templates,Variadic Templates,C++17,Type Alias,我有以下代码: template <template <class...> class Temp, class Specialization> struct IsSpecialization : std::false_type {}; template <template <typename...> class Temp1, template <typename...> class Temp2, typename...
template <template <class...> class Temp, class Specialization>
struct IsSpecialization : std::false_type {};
template <template <typename...> class Temp1,
template <typename...> class Temp2, typename... Ts>
struct IsSpecialization<Temp1, Temp2<Ts...>>
: std::is_same<Temp1<Ts...>, Temp2<Ts...>> {};
struct ExprKindMerge {};
struct ExprKindSequence {};
template <class Tag, class... Args>
struct Expr {
std::tuple<Args...> tup;
constexpr std::tuple<Args...> toStdTuple() const {
return this->tup;
}
constexpr std::size_t size() const noexcept {
return std::tuple_size<decltype(tup)>{};
}
};
template <class...Args>
using MergeExpr = Expr<ExprKindMerge, Args...>;
template <class...Args>
using SequenceExpr = Expr<ExprKindSequence, Args...>;
模板
结构IsSpecialization:std::false_type{};
模板
结构专业化
:std::是相同的{};
结构ExprKindMerge{};
结构ExprKindSequence{};
模板
结构表达式{
std::tuple-tup;
constexpr std::tuple tostduple()const{
返回此->tup;
}
constexpr std::size\u t size()const noexcept{
返回std::tuple_size{};
}
};
模板
使用mergexpr=Expr;
模板
使用SequenceExpr=Expr;
此函数有时接收一个sequencexpr
作为模板参数:
template <class FullExpr>
auto f(FullExpr expr) {
///**************THIS RETURNS FALSE I EXPECT TRUE
///Type of full expr is Expr<ExprKindSequence, ...> which is
/// the expansion of SequenceExpr<...>
if constexpr (IsSpecialization<SequenceExpr, FullExpr>::value)
//...
}
模板
自动f(FullExpr expr){
///**************这返回FALSE,我希望返回TRUE
///完整expr的类型是expr,它是
///SequenceExpr的扩展
if constexpr(IsSpecialization::value)
//...
}
我希望能够检测
FullExpr
是否是SequenceExpr
的专门化,但由于未知原因失败。如果您只对SequenceExpr
的专门化感兴趣,请,我能想象的最好的方法是添加一个专门化IsSpecialization
,定义如下
template <typename... Ts>
struct IsSpecialization<SequenceExpr, Expr<ExprKindSequence, Ts...>>
: std::true_type
{ };
的专门化是上述匹配的专门化
,您将得到true
;我不知道你到底想要什么
下面是一个完整的工作示例
#include <tuple>
#include <iostream>
#include <type_traits>
template <template <typename...> typename Temp, typename Specialization>
struct IsSpecialization : std::false_type
{ };
template <template <typename...> class Temp1,
template <typename...> class Temp2, typename... Ts>
struct IsSpecialization<Temp1, Temp2<Ts...>>
: std::is_same<Temp1<Ts...>, Temp2<Ts...>>
{ };
struct ExprKindMerge {};
struct ExprKindSequence {};
template <typename Tag, typename... Args>
struct Expr
{
std::tuple<Args...> tup;
constexpr std::tuple<Args...> toStdTuple () const
{ return this->tup; }
constexpr std::size_t size () const noexcept
{ return std::tuple_size<decltype(tup)>{}; }
};
template <typename ... Args>
using MergeExpr = Expr<ExprKindMerge, Args...>;
template <typename ... Args>
using SequenceExpr = Expr<ExprKindSequence, Args...>;
template <typename ... Ts>
struct IsSpecialization<SequenceExpr, Expr<ExprKindSequence, Ts...>>
: std::true_type
{ };
template <class FE>
auto f (FE expr)
{ std::cout << IsSpecialization<SequenceExpr, FE>::value << std::endl; }
int main ()
{
f(SequenceExpr<int, long>{}); // print 1
f(Expr<ExprKindSequence, int, long>{}); // print 1 (?)
f(Expr<int, long>{}); // print 0
f(int{}); // print 0
}
#包括
#包括
#包括
模板
结构IsSpecialization:std::false\u类型
{ };
模板
结构专业化
:std::是否相同
{ };
结构ExprKindMerge{};
结构ExprKindSequence{};
模板
结构表达式
{
std::tuple-tup;
constexpr std::tuple tostduple()const
{返回此->tup;}
constexpr std::size\u t size()const noexcept
{return std::tuple_size{};}
};
模板
使用mergexpr=Expr;
模板
使用SequenceExpr=Expr;
模板
结构专业化
:std::true\u类型
{ };
模板
自动f(FE expr)
{std::cout失败的原因很简单。对于SequenceExpr
,Temp2
被推断为Expr
,Ts.
被推断为ExprKindSequence,extrargs…
。然后Temp1
被推断为Expr
,显然与Temp2
不同
我知道没有完全通用的方法可以做到这一点。毕竟,对于IsSpecialization
,这样一个假设的模板可能需要返回true
如果我们将其限制为在可推断上下文中使用其参数的别名模板(在您的示例中就是这种情况),那么一种可能的方法是问这样一个问题:“我可以从专门化中推断Ts.
中的Temp
?”:
名称空间详细信息{
模板类类型{};
模板
无效推导出(类型);
}
模板
结构IsSpecialization:std::false_type{};
模板
结构专业化
:std::true_type{};
静态断言(IsSpecialization());
静态断言(IsSpecialization());
静态断言(!IsSpecialization());
静态断言(!IsSpecialization());
但您感兴趣的是单一类型traitsIsSpecialization
,它可以检测一个类型是泛型容器的专门化,还是只检查SequenceExpr
(可能还有一个很短的别名列表)?@max66我想知道我的函数在顶级FullExpr接收的是不是SequenceExpr。SequenceExpr是Expr的别名。“它因未知原因失败”-它到底是如何失败的?@Edgarokyan我以前更改过。可能还没有刷新,请等待几分钟再刷新。@VTT true。无论如何,这不是本文的要点。事实上,我正在做一些稍微不同的事情,但这可以作为说明。
#include <tuple>
#include <iostream>
#include <type_traits>
template <template <typename...> typename Temp, typename Specialization>
struct IsSpecialization : std::false_type
{ };
template <template <typename...> class Temp1,
template <typename...> class Temp2, typename... Ts>
struct IsSpecialization<Temp1, Temp2<Ts...>>
: std::is_same<Temp1<Ts...>, Temp2<Ts...>>
{ };
struct ExprKindMerge {};
struct ExprKindSequence {};
template <typename Tag, typename... Args>
struct Expr
{
std::tuple<Args...> tup;
constexpr std::tuple<Args...> toStdTuple () const
{ return this->tup; }
constexpr std::size_t size () const noexcept
{ return std::tuple_size<decltype(tup)>{}; }
};
template <typename ... Args>
using MergeExpr = Expr<ExprKindMerge, Args...>;
template <typename ... Args>
using SequenceExpr = Expr<ExprKindSequence, Args...>;
template <typename ... Ts>
struct IsSpecialization<SequenceExpr, Expr<ExprKindSequence, Ts...>>
: std::true_type
{ };
template <class FE>
auto f (FE expr)
{ std::cout << IsSpecialization<SequenceExpr, FE>::value << std::endl; }
int main ()
{
f(SequenceExpr<int, long>{}); // print 1
f(Expr<ExprKindSequence, int, long>{}); // print 1 (?)
f(Expr<int, long>{}); // print 0
f(int{}); // print 0
}
namespace detail {
template<class> class type {};
template<template<class...> class Temp, class...Ts>
void try_deduce(type<Temp<Ts...>>);
}
template <template <class...> class, class, class = void>
struct IsSpecialization : std::false_type {};
template <template <typename...> class Temp, class Specialization>
struct IsSpecialization<Temp, Specialization,
decltype(detail::try_deduce<Temp>(detail::type<Specialization>()))>
: std::true_type {};
static_assert(IsSpecialization<SequenceExpr, SequenceExpr<int>>()());
static_assert(IsSpecialization<Expr, SequenceExpr<int>>()());
static_assert(!IsSpecialization<MergeExpr, SequenceExpr<int>>()());
static_assert(!IsSpecialization<SequenceExpr, MergeExpr<int>>()());