C++ 基于部分模板的专门化与显式部分模板专门化
给定一个模板,例如C++ 基于部分模板的专门化与显式部分模板专门化,c++,templates,c++11,lambda,template-meta-programming,C++,Templates,C++11,Lambda,Template Meta Programming,给定一个模板,例如foo: template<typename... ARGS> struct foo {}; 第二个部分专门化不是比第一个更专门化,并且必须实例化而不是模板参数专门化吗? 一些背景: 我目前正在为基于的模板元编程编写多变量lambda表达式 如本文所示,如果给定类似Haskell的let表达式,可以很容易地开发tmp lambda表达式。在我的例子中,我扩展了论文的内容,开发了基于变量模板的多变量let表达式(通过转换多个嵌套的一元let表达式),然后实现了多变量
foo
:
template<typename... ARGS>
struct foo {};
第二个部分专门化不是比第一个更专门化,并且必须实例化而不是模板参数专门化吗?
一些背景:
我目前正在为基于的模板元编程编写多变量lambda表达式
如本文所示,如果给定类似Haskell的let
表达式,可以很容易地开发tmp lambda表达式。在我的例子中,我扩展了论文的内容,开发了基于变量模板的多变量let表达式(通过转换多个嵌套的一元let表达式),然后实现了多变量lambda表达式
我的lambda表达式模板,tml::multi_lambda
,定义如下:
template<typename BODY , typename... VARIABLES>
struct multi_lambda
{
template<typename... ARGS>
using result = tml::eval<tml::multi_let<VARIABLES...,
ARGS...,
BODY
>>;
};
template<typename VARIABLE , typename VALUE , typename BODY>
struct lambda
{
template<typename ARG>
using result = tml::eval<tml::let<VARIABLE , ARG , BODY>>;
};
tml::eval
实例化通用模板专门化(为通用可计算表达式设计),而不是lambda的部分专门化
编辑:tml::eval和SSCCE的实施
tml::eval
是一个元函数,用于计算任何类型的表达式,并返回结果。默认实现专门用于三种情况:
template<typename E>
struct evaluate_impl<E>
{
using result = E;
};
tml::eval
以使用该自定义参数对表达式求值:忽略表达式的参数并传递和求值自定义参数:
template<template<typename...> class F , typename... PLACEHOLDERS , typename... ARGS>
struct evaluate_impl<F<PLACEHOLDERS...>,ARGS...> : public F<tml::eval<ARGS>...>
{};
最后,用户可以专门化eval_impl
来覆盖默认行为,或使角落案例工作。例如,我的单变量lambda表达式模板,定义如下:
template<typename BODY , typename... VARIABLES>
struct multi_lambda
{
template<typename... ARGS>
using result = tml::eval<tml::multi_let<VARIABLES...,
ARGS...,
BODY
>>;
};
template<typename VARIABLE , typename VALUE , typename BODY>
struct lambda
{
template<typename ARG>
using result = tml::eval<tml::let<VARIABLE , ARG , BODY>>;
};
我遇到问题的多变量lambda表达式采用类似的方法:
template<typename... VARIABLES , typename BODY , typename... ARG>
struct evaluate_impl<tml::multi_lambda<BODY,VARIABLES...>,ARGS...>
{
using result = typename tml::multi_lambda<BODY,VARIABLES...>::template result<ARGS...>;
};
在以下情况下,lambda_2
的评估失败:
functional.hpp:167:76:错误:“struct tml::impl::evaluate_impl”的类模板实例化不明确
使用eval=typename impl::evaluate\u impl::result;
^
functional.hpp:116:16:错误:候选项为:struct tml::impl::evaluate\u impl
结构评估\u impl:
^
在main.cpp:24:0中包含的文件中:
lambda.hpp:160:16:错误:struct tml::impl::evaluate\u impl
结构评估\u impl:
我使用的是GCC4.8.2它看起来像是在您的multi_lambda中,您正在用变量声明模板。。。最后
template<typename BODY , typename... VARIABLES>
struct multi_lambda
{
//...
};
模板
结构多λ
{
//...
};
也许在您的使用中,您应该使用:
using lambda_2 = tml::multi_lambda<F<_1,_1,_2,_2>,_1,_2>;
使用lambda_2=tml::multi_lambda;
首先,您应该真正了解什么是SSCCE,尤其是的“完整”部分。另外,短。也就是说,我试图创建一个SSCCE,它似乎重现了您的问题,请参见我的答案末尾。查看您收到的错误消息,第三个专门化的实际代码看起来更像
template<template<typename...> class F ,
typename... PLACEHOLDERS ,
typename ARG ,
typename... ARGS>
struct evaluate_impl<F<PLACEHOLDERS...>,ARG,ARGS...>
: public F<tml::eval<ARG,ARGS>...>
{};
这个问题可能会消失
最后,我曾经得到过一个和你相似的错误
更新:使用下面评论中的SSCCE,只需在
foo
时禁用F
的专门化,即可解决这种情况。情况如下所示:
typename std::enable_if<!std::is_same<F<>,foo<>>::value>::type
typename std::enable_if,foo>::value>::type
或者根据您的SSCCE查看完整的。这样,您也可以添加
ARG
,因为这两个专门化现在应该是相互排斥的。@DieterLücking写一个显式名称而不是那个示例?您的意思是“第一个部分专门化不是比第二个更显式…”谢谢您的建议。我指的是第二个(fooone),而不是第一个(通用模板参数T
one)。你能提供一个SSCCE来显示你的问题吗?@Danvil你为什么这么认为?哦,对不起,那是个打字错误:(感谢您的努力。您是对的,第三个专门化确实使用了一个额外的arg来拒绝无参数的情况。为了简化问题,我省略了这一点。这是大量的代码,当我发布问题时,我试图描述实际的问题,而不只是复制粘贴整个库。但是您是对的ht,我在这个问题上发表了一篇好的SSCCE文章,这是非常错误的。我有很多问题要写一个简单的工作示例,而不发表数百行模板元编程代码:(另外,您的SSCCE正是我所处的情况。非常感谢。@Manu343726您是否可以按照我的建议,删除ARG
以解决您的问题?您仍然可以使用static\u assert(sizeof…(ARGS)>0“至少需要一个ARGS”拒绝无参数情况)
如果您需要,请在结构中。否则,请将我的SSCE扩展到显示您需要的内容,这样每个人都有公平的机会来帮助您。嗯,我可以根据参数包的长度尝试进行SFINAE。谢谢,我明天会尝试。我将发表评论(可能还会对问题进行编辑)关于结论。谢谢。@Manu343726欢迎来到§14.8.2.4的精彩世界。看看9/10,并确保你阅读了它,这实际上是由此产生的。鉴于你的问题,我们讨论了你的实际案例可能是什么的几个选项,每个选项都需要不同的具体分析。如果你对此感兴趣,我建议你接受了一个案例,并向相应的SSCCE提出了一个新问题。
template<typename BODY , typename... VARIABLES>
struct multi_lambda
{
//...
};
using lambda_2 = tml::multi_lambda<F<_1,_1,_2,_2>,_1,_2>;
template<template<typename...> class F ,
typename... PLACEHOLDERS ,
typename ARG ,
typename... ARGS>
struct evaluate_impl<F<PLACEHOLDERS...>,ARG,ARGS...>
: public F<tml::eval<ARG,ARGS>...>
{};
template<template<typename...> class F ,
typename... PLACEHOLDERS ,
typename... ARGS>
struct evaluate_impl<F<PLACEHOLDERS...>,ARGS...>
: public F<tml::eval<ARGS>...>
{};
typename std::enable_if<!std::is_same<F<>,foo<>>::value>::type