gpt4 book ai didi

c++ - 部分模板-基于模板的特化与显式部分模板特化

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:48:19 26 4
gpt4 key购买 nike

给定一个模板,例如 foo :

template<typename... ARGS>
struct foo {};

还有模板 bar 的两个偏特化:

template<template<typename...> class T , typename... ARGS>
struct bar<T<ARGS...>>
{};

template<typename... ARGS>
struct bar<foo<ARGS...>>
{};

第二个部分特化不是比第一个更特化并且必须实例化而不是模板-模板参数特化吗?

一些上下文:

我目前正在为基于 this paper 的模板元编程编写多变量 lambda 表达式。

如论文所示,给定类似 Haskell 的 let 表达式,可以轻松开发 tmp lambda 表达式。在我的例子中,我扩展了开发基于可变参数模板的多变量 let 表达式(通过 curryfying 多个嵌套的一元 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
>>;
};

其中 tml::eval 是用于计算表达式的元函数,例如 Boost::mpl mpl::apply(有关更多上下文,请参阅 my previous question)。

求值函数 tml::eval 既专门用于通用函数表达式,也专门用于此 lambda 表达式。那就是上面例子的两个特化。

当我尝试计算 lambda 表达式时,例如:

using lambda = tml::multi_lambda<_1,_2, f<_1,_2>>; //f is a function, 
//_1 _2 are placeholders
using result = tml::eval<lambda,int,int>; //Evaluate lambda with int int as parameters

tml::eval 实例化通用模板-模板特化(专为通用可评估表达式设计)而不是 lambda 的部分特化。

编辑:tml::eval 和 SSCCE 的实现

tml::eval 是一个元函数,用于计算任何类型的表达式并返回结果。默认实现专门针对三种情况:

  1. 表达式不是一个函数,只是一个值:这样的表达式求值的结果就是表达式本身:

    template<typename E>
    struct evaluate_impl<E>
    {
    using result = E;
    };
  2. 表达式是一个函数:求值结果是函数的result成员类型的值。函数的参数也被评估(为了处理嵌套表达式):

    template<template<typename...> class F , typename... ARGS>
    struct evaluate_impl<F<ARGS...>> : public F<tml::eval<ARGS>...>
    {};
  3. 表达式是一个函数,更多的参数被传递给 tml::eval 以使用自定义参数计算表达式:表达式的参数被忽略,自定义被传递和计算:

    template<template<typename...> class F , typename... PLACEHOLDERS , typename... ARGS>
    struct evaluate_impl<F<PLACEHOLDERS...>,ARGS...> : public F<tml::eval<ARGS>...>
    {};

所以 tml::eval 只是一个覆盖 typename ::result 的模板别名:

template<typename... ARGS>
using eval = typename eval_impl<ARGS...>::result;

最后,用户可以专门化 eval_impl 来覆盖默认行为,或者使极端情况起作用。比如我的单变量lambda表达式模板,定义如下:

template<typename VARIABLE , typename VALUE , typename BODY>
struct lambda
{
template<typename ARG>
using result = tml::eval<tml::let<VARIABLE , ARG , BODY>>;
};

特化 eval_impl 使 lambda 表达式的计算有效:

template<typename VARIABLE , typename BODY , typename ARG>
struct evaluate_impl<tml::lambda<VARIABLE,BODY>,ARG>
{
using result = typename tml::lambda<VARIABLE,BODY>::template result<ARG>;
};

我遇到问题的多变量 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...>;
};

但是 tml::eval 没有工作(就像一个变量对应物),而是实例化了默认 evaluate_impl 实现的案例三,或者由于不明确的特化而失败(案例三与 multi_lambda 特化)。

这是一个 SSCCE:

//An example function:
template<typename... ARGS>
struct F
{
using result = std::integral_constant<std::size_t,sizeof...(ARGS)>;
};


//This works fine:

using lambda_1 = tml::lambda<_1,F<_1,_1,_1,_1>>;
using result_1 = tml::eval<lambda_1,int>; //Call the lambda with int as parameter


//This doesn't work:

using lambda_2 = tml::multi_lambda<_1,_2,F<_1,_1,_2,_2>>;
using result_2 = tml::eval<lambda_2,int,int>; //Call the lambda with two int as parameters.

lambda_2 的评估失败:


functional.hpp:167:76: error: ambiguous class template instantiation for 'struct tml::impl::evaluate_impl<tml::impl::multi_lambda<tml::placeholders::_1, tml::placeholders::_2, f<tml::placeholders::_1, tml::placeholders::_1, tml::placeholders::_2, tml::placeholders::_2> >, int, int>'
using eval = typename impl::evaluate_impl<EXPRESSION , ARGS...>::result;
^
functional.hpp:116:16: error: candidates are: struct tml::impl::evaluate_impl<F<PLACEHOLDERS ...>, ARG, ARGS ...>
struct evaluate_impl<F<PLACEHOLDERS...> , ARG , ARGS...> :
^
In file included from main.cpp:24:0:
lambda.hpp:160:16: error: struct tml::impl::evaluate_impl<tml::impl::multi_lambda<BODY, VARIABLES ...>, ARGS ...>
struct evaluate_impl<multi_lambda<BODY,VARIABLES...>,ARGS...> :

我使用的是 GCC4.8.2

最佳答案

首先,您应该真正了解什么是 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>...>
{};

请注意对 ARG 的额外明确提及,这似乎是多余的,并且可能会导致您的情况出现歧义。如果将其替换为

template<template<typename...> class F ,
typename... PLACEHOLDERS ,
typename... ARGS>
struct evaluate_impl<F<PLACEHOLDERS...>,ARGS...>
: public F<tml::eval<ARGS>...>
{};

问题可能会消失。

最后,here's an SSCCE我曾经遇到过与您类似的错误。


更新:根据您在下方评论中的 SSCCE,当 Ffoo 时,只需禁用其特化即可解决这种情况。条件看起来像这样:

typename std::enable_if<!std::is_same<F<>,foo<>>::value>::type

或查看完整的 live example基于你的 SSCCE。这样,您可能还可以将 ARG 添加回来,因为现在这两个特化应该是互斥的。

关于c++ - 部分模板-基于模板的特化与显式部分模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23393962/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com