2016-06-12 47 views
1

假设我正在开发一个类Vec<T>,它表示一个数学向量,其元素类型为T过载类型转换为初始化列表

为了方便我创建了一个需要std::initializer_list构造:

Vec(std::initializer_list<T> l) 
    : size(l.size()) 
{ 
    data = new T[size]; 
    std::copy(l.begin(), l.end(), data); 
} 

所以,现在我可以做以下的事情:

v += Vec<int>({ 1, -1 }); 
bool equal = (v == Vec<int>({ 8, 9 })); 

等等......不过,这将是巨大的,如果我可以写得更短,更清洁:

v += { 1, -1 }; 
bool equal = v == { 8, 9 }; 

我该如何实现这样的行为?我想我可以将类型转换运算符重载到std::initializer_list,但它甚至被认为是正常的做法吗?编译时间和性能有多糟糕,甚至可以工作?

std::vector怎么样,它支持类似于C++ 11中的东西吗?

编辑:

所以,这里是我的operator+=

Vec<T> & operator+=(const Vec<T> &v) 
{ 
    assert(size == v.size); 
    for (int i = 0; i < size; ++i) 
     data[i] += v.data[i]; 
    return *this; 
} 

中注释的答案是正确的,initializer_list实际上赋值运算符之后的工作原理:

v += {2, 3}; 
v -= {2, 3}; 

我试着写这样的东西:

v = v + {2, 3}; 

这就是为什么它不起作用。

所以,结论是:你可以在赋值和复合赋值运算符之后像这样使用它,但是对于二进制算术运算符和比较它不起作用,我正确吗?我想创建自定义文字也不是一个选项。

顺便问一下,怎么样:

const Vec<float> a{ 1.01, 2.02 }; // error: conversion from 'double' to 'float' requires a narrowing conversion test_app 
const Vec<float> b{ 1.01f, 2.02f }; // works, obviously 

我能做些什么,以使隐式转换在第一种情况?

EDIT2

这里是operator+

friend Vec<T> operator+(Vec<T> v, const Vec<T> &w) 
{ 
    v += w; // reuse compound assignment 
    return v; // return the result by value (uses move constructor) 
} 
+1

显示你的'operator + ='。这应该已经按照您的描述工作了。 –

+1

'v == {8,9}'在语法上无效。 – cpplearner

+0

['operator + ='just works](http://rextester.com/NBE83364),没有额外的努力。我想大多数其他运营商也会这样。 'operator =='是一个例外;在顶部,我不太清楚为什么它在这里很特别。 –

回答

1

不幸的是,v + {1, 2}是不是在C++对语法规则结构良好表达。对于每个操作数,大多数二元运算符仅仅使用表达式,并且支撑列表不是表达式。复合赋值运算符+=是特殊的,因为赋值也接受初始化子句的右侧操作数,所以v += {1, 2}恰好工作。

一些替代方案:

operator+(v, {1, 2}) 
v + Vec<int>({1, 2}) 
+0

感谢您的回答。我认为另一个选择是创建像add或isEqualTo这样的函数,在这里你可以很容易地传递初始化列表,如下所示: 'v.isEqualTo({1,2,3});' –

1

如何v.equals({8, 9})?另外,虽然v + {1, 2, 3, 4}不可能,但您可能仍会像许多向量矩阵实现那样重载逗号运算符(不适用于int,但对于特定类型,如:v + (V(1), 2, 3, 4),如果您喜欢,则添加宏)。

+0

是的,我已经选择像你的'等号'一样的方法,看看我的评论接受的答案。 顺便说一句,我已经在一些库中看到了逗号实现(比如OpenCV),但我宁愿远离这种设计。不是一个特别明显的界面) –