是否有任何方法可以在一对一的关系中限制 c++ 模板类参数?

Is there anyway to restrict c++ template class parameters within one-to-one relationship?

提问人:lhh2001 提问时间:9/13/2023 更新时间:9/13/2023 访问量:79

问:

例如,有一个模板类:

template<typename A, typename B>
class Example;

如果一对 (A, B) 是专门的,那么其他类型的就不能专门用于 A。例如,允许 (B, C),但不允许 (A, C)。

Example<int, double> E1, E2, E3;  // OK
Example<int, double> E4;          // OK
Example<int, bool> E5;            // Not Allowed (Because <int, double> already exists)
Example<bool, double> E6;         // OK
Example<double, double> E7;       // OK
Example<double, int> E8;          // Not Allowed (<double, double> already exists)

我尝试在运行时在模板参数 A 和 B 之间使用 std::map,但是在编译过程中是否有办法做到这一点?喜欢 SFINAE 或其他技术?

C++ 模板 C++17 SFINAE

评论

3赞 Swift - Friday Pie 9/13/2023
这个想法的概念的问题在于,编译单元之间的实例化顺序是未定义的\实现定义的,并且是该单元的本地,但实例化的实体是 ODR 使用的。因此,任何使另一个替代成为非法的替代,也将处于违反ODR的状态,其汇编单元不是它所发生的。

答:

5赞 Sebastian Redl 9/13/2023 #1

我能想到的唯一真正的方法是让它成为两个模板参数,而是一个提供到第二种类型的固定映射的参数:

template <typename T>
struct ExampleAssociated { static_assert(false, "must specialize this"); };
template <typename A>
class Example {
  using B = typename ExampleAssociated<A>::type;
};

template <>
struct ExampleAssociated<int> { using type = double; };
template <>
struct ExampleAssociated<bool> { using type = double; };
// ...

Example<int> E1; // OK
Example<bool> E6; // OK
4赞 HolyBlackCat 9/13/2023 #2

只需添加一个函数定义,该定义依赖于 但不依赖于 .friendAB

template <typename> struct tag {};

template <typename A, typename B>
class Example
{
    friend constexpr void a_tag(tag<A>) {}
};

如果您尝试使用两个不同的 s 但相同来实例化它,您将得到该函数的重复定义错误,因为两个不同的实例化将尝试定义它。BA

请注意,它只检查单个翻译单元内部(因为该函数是隐式的)。如果要跨 TU 进行相同的测试,则需要额外保留运行时映射。inline

评论

0赞 Jarod42 9/13/2023
返回可能有助于链接器跨 TU 发现问题。tag<B>
0赞 HolyBlackCat 9/13/2023
@Jarod42 不,没有运气。尝试返回,也什么都没有。也许需要一些链接器标志。__PRETTY_FUNCTION__