【问题标题】:Creating an template<T> only for such T that have operator/ defined仅为定义了 operator/ 的 T 创建模板<T>
【发布时间】:2015-02-20 19:52:44
【问题描述】:

我想为类型定义一个template&lt;T&gt;,但我必须确保只有定义了operator/operator+ 的类型才能作为T 传递

这是因为我希望能够获得其中两个(属于同一类型)的插值,例如:

template<class T>
class Key final : public KeyBase{
public: //to keep the example simple
    //unsigned timeMS; <-- iherited from KeyBase
    T value;

public:
    Key(unsigned timeMS, const T &value) 
        : KeyBase(timeMS), value(value){}
    T inline getValue(){ return value; }
};

Key<float> start = {10, 5.0f};
Key<float> end = {15, 3.0f};
float ratioAtTime12 = 12 / (end.timeMS - start.timeMS);
float valueAtTime12 = start.value + (end.value - start.value) * ratio;

//Point2D is my own custom type that have operator+, - and / defined
Key<Point2D> start2 = {10, Point2D(10, 15)};
Key<Point2D> end2 = {15, Point2D(111, 6)};
...

Key<Character> start3 = {10, Character("Alan")}; //SHOULD generate an error
//because my custom Character type has no operator+, - or / defined!

对于floatint 等简单类型,没关系。但是,如果没有定义operator/operator+,如何防止将复杂类型用作T

【问题讨论】:

  • 如果提到的运算符被用于未定义的类的实例上,则会出现编译错误。所以类型是隐式约束的。
  • 如果没有定义这些操作符,你想让它做什么?
  • @GézaTörök 我同意。但是,我想在创建这样的对象的那一刻得到一个错误(从我的角度来看,甚至声明它是没有意义的),而不是等待操作员的使用。
  • @MarkB 我想最好生成一个编译时错误。

标签: c++ templates operators


【解决方案1】:

如果您想要一个不包含通过 ADL 等找到的大量运算符的漂亮错误消息,您可以定义特征:

template <typename, typename=void>
struct isAddable : std::false_type {};

template <typename T>
struct isAddable<T, decltype(void(std::declval<T>() + std::declval<T>()))>
    : std::true_type {};

template <typename, typename=void>
struct isDividable : std::false_type {};

template <typename T>
struct isDividable<T, decltype(void(std::declval<T>() / std::declval<T>()))>
    : std::true_type {};

...并使用静态断言。

static_assert( isAddable<T>{} && isDividable<T>{}, "Invalid T!" );

或者,要获得更具体的信息:

static_assert( isAddable<T>{}, "T not addable!" );
static_assert( isDividable<T>{}, "T not dividable!" );

Demo.


您还可以使用方便的宏来定义此类特征。

#define VAL std::declval<T>()

#define DEF_TRAIT(name, expression)                                  \
template <typename, typename=void> struct name : std::false_type {}; \
template <typename T>                                                \
struct name<T, decltype(void(expression))> : std::true_type {};

DEF_TRAIT(isDividable, VAL / VAL)
DEF_TRAIT(isAddable, VAL + VAL)

Demo.

【讨论】:

  • 太棒了 :) 感谢您对包含演示的详细回答,先生。
  • 这会检查T / TT + T 是否有效,但如果没有为相同类型的两个对象进行重载,则会失败。
  • @0x499602D2 无关。该问题指出“这是因为我希望能够获得其中两个(属于同一类型)的插值,”
猜你喜欢
  • 1970-01-01
  • 2010-12-10
  • 1970-01-01
  • 2021-04-16
  • 2012-04-27
  • 2019-09-14
  • 1970-01-01
  • 1970-01-01
  • 2011-10-31
相关资源
最近更新 更多