编译时检查是否有两个具有相同模板参数的模板实例化
Compiletime check if there are two template instantiations with identical template-parameter
如果我有两个不相关的模板 A
和 B
,我该如何执行编译时检查以查看是否有两个相同的参数。例如。如果我有一些参数类型 P1
和 P2
,我想让客户端实例化 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
如果每个参数 typ 都有一个唯一的 id(掩码),这就有效,因此我可以对所有掩码进行 OR,看看它们的数量是否等于 Checker
的参数包的大小。
这个解决方案不好,因为客户端可能忘记实例化Checker
模板。
我想知道是否可以在后台进行更多检查?
This solution is not good because a client can forget to instatiate the Checker
template.
很好的直觉 - 因此您应该阻止客户端在实例化 Checker
之前实例化 A
和 B
。您可以通过将它们提供为只能从 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;
如果您希望 A
和 B
由用户提供,您可以将 Checker
的类型别名作为模板 - 但这种做法违背了它的目的,因为用户已经首先访问了 A
和 B
。
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>;
};
如果我有两个不相关的模板 A
和 B
,我该如何执行编译时检查以查看是否有两个相同的参数。例如。如果我有一些参数类型 P1
和 P2
,我想让客户端实例化 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
如果每个参数 typ 都有一个唯一的 id(掩码),这就有效,因此我可以对所有掩码进行 OR,看看它们的数量是否等于 Checker
的参数包的大小。
这个解决方案不好,因为客户端可能忘记实例化Checker
模板。
我想知道是否可以在后台进行更多检查?
This solution is not good because a client can forget to instatiate the
Checker
template.
很好的直觉 - 因此您应该阻止客户端在实例化 Checker
之前实例化 A
和 B
。您可以通过将它们提供为只能从 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;
如果您希望 A
和 B
由用户提供,您可以将 Checker
的类型别名作为模板 - 但这种做法违背了它的目的,因为用户已经首先访问了 A
和 B
。
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>;
};