我不确定如何解释这个,所以我会给出代码。
我正在尝试使用 C++ 模板对 Chuch 数字进行编码(为了好玩,也为了帮助我理解模板元编程)。
struct Z {
static constexpr unsigned int n = 0;
template<typename T>
using replace = T;
};
template<typename T>
struct S {
static constexpr unsigned int n = T::n + 1;
template<typename U>
// using replace = T::replace<U>;
using replace = typename T::template replace<U>;
};
所以,我尝试了 using replace = T::replace<U>
,这确实不起作用,而且我不知道为什么(我使用的是 GCC),如果有人能向我解释原因,我将不胜感激(参见链接以下)。当我尝试使用 Clang 进行编译时,它给了我一条很好的错误消息:
首先,use 'template' keyword to treat 'replace' as a dependent template name
, 然后 template argument for template type parameter must be a type; did you forget 'typename'?
...
然后我设法制作了using replace = typename T::template replace<U>
编译,这似乎是合法的。
但我真正需要的是类似 S<T::replace<U>>
的东西,我发现没有办法工作。
我尝试将其更改为 T::replace<U>::succ
同样,并定义 succ
成为S<Z>
在 Z
和 S<S<T>>
在 S
,但我也无法让它工作......
有什么想法吗? :(
最佳答案
教会数字的元数为 2;他们接受一个仿函数和一个值,并将仿函数 n
次应用于该值。在元编程中,这可以表示为具有 2 个模板参数的模板,第一个是模板模板参数:
struct Z {
template<template<typename> class F, typename x>
using replace = x;
};
template<typename T>
struct S {
template<template<typename> class F, typename x>
using replace = F<typename T::template replace<F, x>>;
};
我们可以用 F
作为 integral_constant
的后继函数来测试它(这在 lambda 演算中并不是真正的值,但它并不关心这个):
#include <type_traits>
template<typename N> using s = typename std::integral_constant<typename N::value_type, N::value + 1>;
static_assert(S<S<Z>>::replace<s, std::integral_constant<int, 2>>::value == 4, "arithmetic!");
如果你想柯里化(Currying)replace
,语法会稍微复杂一些:
struct Z {
template<template<typename> class F> struct replace {
template<typename x> using apply = x;
};
};
template<typename T>
struct S {
template<template<typename> class F> struct replace {
template<typename x> using apply = F<typename T::template replace<F>::template apply<x>>;
};
};
严格来说,通过采用模板模板参数,我们引入了无类型 lambda 演算中不存在的区别(仿函数和值之间)。解决这个问题的方法是让我们的仿函数作为包含应用程序机制的类型名参数:
struct Z {
template<typename F> struct replace {
template<typename x> using apply = x;
};
};
template<typename T>
struct S {
template<typename F> struct replace {
template<typename x> using apply = typename F::template apply<typename T::template replace<F>::template apply<x>>;
};
};
和演示:
#include <type_traits>
struct s { template<typename N> using apply = typename std::integral_constant<typename N::value_type, N::value + 1>; };
static_assert(S<S<Z>>::replace<s>::template apply<std::integral_constant<int, 2>>::value == 4, "arithmetic!");
关于c++ - 从属模板名称参数替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21758634/