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

Compiletime check if there are two template instantiations with identical template-parameter

本文关键字:实例化 参数 是否 检查 编译 两个      更新时间:2023-10-16

如果我有两个不相关的模板AB,我如何执行编译时检查以查看是否有两个相同的参数。 例如,如果我有一些参数类型P1P2,我想让客户端实例化A<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

如果每个参数类型都有一个唯一的 id(掩码(,因此我可以或所有掩码,看看 1 的数量是否等于 Checker 参数包的大小,这就可以工作。

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

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

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

良好的直觉 - 因此,您应该防止客户端在实例化Checker之前实例化AB。您可以通过将它们作为类型别名提供来实现此目的,只能从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>;
};