如何拥有受约束的运算符模板?

How can I have a constrained operator template?

本文关键字:运算符 受约束 何拥有 拥有      更新时间:2023-10-16

我正在尝试使我的类可转换为任何枚举类型。

enum dst_1 { /*...*/ };
enum dst_2 { /*...*/ };
class src { /*...*/ };
src s;
dst_1 d1 = s;
dst_2 d2 = s;

不想为每个枚举类型手动添加转换,因此以下解决方案不可接受的:

// OK, but tedious - you must consider each enum type
class src
{
public:
operator dst_1() const { /*...*/ }
operator dst_2() const { /*...*/ }
// ...
};

使转换成为模板不适用于模板参数无法推断

// NOT OK: T cannot be deduced
class src
{
public:
template< typename T > using Enum = enable_if_t< is_enum_v< T >, T >;
template< typename T > operator Enum< T >() const { /*...*/ }
};

我能找到的唯一解决方案是可变参数模板,但我不喜欢它,因为它迫使用户指定枚举计划使用:

// ALMOST OK, but still tedious - you must know in advance what enums will be used
src< dst_1, dst_2 > s;
dst_1 d1 = s;
dst_2 d2 = s;

那么,有没有更好的解决方案?理想情况下,我想写:

src s;
dst_1 d1 = s;
dst_2 d2 = s;

使转换模板不适用于模板参数无法推断:

它不能以你的方式推导,因为这里T是一个非推导的上下文:

template< typename T > using Enum = enable_if_t< is_enum_v< T >, T >;

这不能像推导出T一样推导

template <typename T> struct identity { using type = T; }
template <typename T> void foo(typename identity<T>::type);
foo(0); // nope

编写此运算符模板的正确方法是:

template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
operator T() const;

或者:

template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0> using Enum = T;
template <typename T> operator Enum<T>() const;

请注意,别名必须T,而不是其他任何东西。