模板模板和部分专业化:一个谜题

时间:2016-03-10 16:53:47

标签: c++ templates c++11 template-specialization partial-specialization

请考虑以下代码:

B

编译并没有问题。
无论如何,每当决定使用B<void()>时,它必须提供两种类型 我想要实现的是以某种方式默认第二个参数(我知道,部分特化不接受其参数的默认值)并让用户将其定义为B<void(), S<void>>而不是Application.EnableEvents = True
不幸的是,由于模板模板,部分特化以及参数之间存在的依赖性,它们共同导致了一个难题,我在几个小时后就陷入困境。

有没有聪明的解决方案呢? 到目前为止,我已经能够用中间结构解决它,但我不太喜欢它......

3 个答案:

答案 0 :(得分:2)

您可以为此创建一个帮助程序类:

template <typename T> struct default_arg;

template <typename R, typename... Args>
struct default_arg<R(Args...)>
{
    using type = S<R>;
};

template<typename Sign, typename T = typename default_arg<Sign>::type>
struct B;

Demo

答案 1 :(得分:2)

部分特化不接受默认参数,但主要部分不接受。你可以在那里添加它:

template<typename Sig, typename X = S<return_type_t<Sig>>>
struct B;

然后,您需要做的就是为签名实现返回类型元函数。类似的东西:

template <class Sig>
struct return_type;

template <class Sig>
using return_type_t = typename return_type<Sig>::type;

template <class R, class... Args>
struct return_type<R(Args...)> {
    using type = R;
};

答案 2 :(得分:1)

此处我们将B更改为模板别名。

B_t默认arg有效。

B_implB的实现,没有任何默认参数。

B是一个using别名,可获得B_t的结果。

template<class> struct S {};

template<class, class>
struct B_impl;

template<class R, class... Args, template<class...> class C>
struct B_impl<R(Args...), C<R>> {
  void f() { }
};

template<class, class=void>
struct B_t;

template<class R, class...Args>
struct B_t<R(Args...), void>:
  B_t<R(Args...),S<R>>
{};

template<class R, class... Args, template<class...> class C>
struct B_t<R(Args...), C<R>> {
  using type=B_impl<R(Args...), C<R>>;
};

template<class Sig, class Z=void>
using B=typename B_t<Sig,Z>::type;

缺点是B上的模式匹配效果不佳。