template<class D>
struct strong_add {
friend D operator+( D lhs, D const& rhs ) {
lhs += rhs; return lhs;
}
friend D& operator+=( D& lhs, D const& rhs ) {
lhs.v += rhs.v;
return lhs;
}
};
struct myint :
strong_type<int, myint_tag>,
strong_add<myint> {
using strong_type<int, myint_tag>::strong_type;
};
Live example
.
这使用CRTP。
+
以值作为lhs参数,因为如果您有廉价的移动,复制类型会很昂贵,比如
std::string
:
a + b + c + d + e
天真地
const&, const&
另外,我们每
+
,因为我们在操作员的每个返回点创建了一个全新的对象。
用一个
value, const&
加上,第一
a
被复制。然后我们做
+= b
,然后移动结果,然后
+= c
然后移动结果,然后
+= e
然后移动结果。只有一份复印件。
如果你愿意,我们可以走得更远。
首先,我们这样做:
template<class T>
class detect_strong_type {
template<class X, class Tag>
static std::true_type tester( strong_type<X, Tag>const* );
static std::false_type tester( void* );
public:
using type=decltype( tester( (T*)nullptr ) );
};
template<class T>
using is_strong_type = typename detect_strong_type<T>::type;
enum class operators {
add, subtract, multiply, divide
};
template<operators o>
using op_tag_t = std::integral_constant<operators, o>;
template<operators o>
constexpr op_tag_t<o> op_tag{};
auto default_op( op_tag_t<operators::add> ) { return [](auto& lhs, auto const& rhs){ lhs += rhs; }; }
auto default_op( op_tag_t<operators::subtract> ) { return [](auto& lhs, auto const& rhs){ lhs -= rhs; }; }
auto default_op( op_tag_t<operators::multiply> ) { return [](auto& lhs, auto const& rhs){ lhs *= rhs; }; }
auto default_op( op_tag_t<operators::divide> ) { return [](auto& lhs, auto const& rhs){ lhs /= rhs; }; }
template<operators op, class D, class...Skip>
void do_operator( op_tag_t<op>, D& lhs, D const& rhs, Skip&&... ) {
default_op( op_tag<op> )( lhs, rhs );
}
template<class D>
struct can_add {
friend D operator+( D lhs, D const& rhs ) {
lhs += rhs; return lhs;
}
friend D& operator+=( D& lhs, D const& rhs ) {
do_operator( op_tag<operators::add>, lhs, rhs );
return lhs;
}
};
template<class D>
struct can_subtract {
friend D operator-( D lhs, D const& rhs ) {
lhs -= rhs; return lhs;
}
friend D& operator-=( D& lhs, D const& rhs ) {
do_operator( op_tag<operators::subtract>, lhs, rhs );
return lhs;
}
};
template<class D>
struct can_multiply {
friend D operator*( D lhs, D const& rhs ) {
lhs *= rhs; return lhs;
}
friend D& operator*=( D& lhs, D const& rhs ) {
do_operator( op_tag<operators::multiply>, lhs, rhs );
return lhs;
}
};
template<class D>
struct can_divide {
friend D operator/( D lhs, D const& rhs ) {
lhs *= rhs; return lhs;
}
friend D& operator/=( D& lhs, D const& rhs ) {
do_operator( op_tag<operators::divide>, lhs, rhs );
return lhs;
}
};
template<class D>
struct can_math:
can_add<D>, can_multiply<D>, can_subtract<D>, can_divide<D>
{};
现在我们教
do_operator
关于
strong_type
:
template<operators op, class D,
std::enable_if_t< is_strong_type<D>{}, bool> =true
>
void do_operator( op_tag_t<op>, D& lhs, D const& rhs ) {
do_operator( op_tag<op>, lhs.v, rhs.v );
}
这个作品:
struct myint :
strong_type<int, myint_tag>,
can_math<myint>
{
using strong_type<int, myint_tag>::strong_type;
};
int main(){
myint a{ 2 };
myint b{ 3 };
myint c = a*b + b - a;
}
Live example
现在,这对强大的运营商来说有点过分了。它让你做的是:
struct some_type: can_add<some_type> {
std::vector<int> values;
friend void do_operator( op_tag_t<operators::add>, some_type& lhs, some_type const& rhs ) {
lhs.values.insert( lhs.values.end(), rhs.values.begin(), rhs.values.end() );
}
};
现在
some_type + some_type
和
some_type += some_type
执行。