编译时检查是否有两个模板实例具有相同的模板参数

时间:2017-06-12 14:40:13

标签: c++ templates c++17

如果我有两个不相关的模板BP1,如何执行编译时检查以查看是否存在两个相同的参数。例如。如果我有一些参数类型P2A<P1>,我想让客户端实例化B<P2>A<P1>,而不是B<P1>Checker<typename... Xx>

我有一个使用可变参数模板using a = A<P1>; using b = B<P1>; using checker = Checker<a, b>; checker::init(); // can be empty // static_assert fails here 的解决方案,必须使用相关模板进行实例化:

Checker

如果每个参数typ都有唯一的id(掩码),那么这是有效的,因此我可以对所有掩码进行OR操作,看看1的数量是否等于Checker参数包的大小。

此解决方案不好,因为客户端忘记来实例化{{1}}模板。

我想知道这项检查是否可以在引擎盖下进行更多的讨论?

1 个答案:

答案 0 :(得分:2)

  

此解决方案不好,因为客户端可能忘记设置Checker模板。

良好的直觉 - 因此,在实例化A之前,您应该阻止客户端实例化BChecker。您可以通过提供仅从Checker访问的类型别名来实现此目的。

namespace detail
{
    template <typename T> struct A;
    template <typename T> struct B;
}

template <typename P0, typename P1>
struct Checker
{
    static_assert(!std::is_same_v<P0, P1>);

    using A = detail::A<P0>;
    using B = detail::B<P1>;
};

用法:

using ClientABProvider = ABProvider<foo, bar>;
using A = typename ClientABProvider::A;
using B = typename ClientABProvider::B;

using ClientABProvider = ABProvider<foo, foo>; // Error!
using A = typename ClientABProvider::A;
using B = typename ClientABProvider::B;

如果您希望AB是用户提供的,那么您可以将Checker的类型别名作为模板 - 但这种方式会失败,因为用户已经首先访问AB

template <typename P0, typename P1>
struct Checker
{
    static_assert(!std::is_same_v<P0, P1>);

    template <template <typename> class XA>
    using A = XA<P0>;

    template <template <typename> class XB>
    using B = XB<P1>;
};