我们假设我正在开发一个类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)
}
答案 0 :(得分:1)
不幸的是,对于语法规则,v + {1, 2}
在C ++中不是一个格式良好的表达式。大多数二元运算符只为每个操作数采用表达式,而支撑列表不是表达式。复合赋值运算符+=
是特殊的,因为赋值还接受右手操作数的 initializer-clause ,因此v += {1, 2}
恰好起作用。
一些替代方案:
operator+(v, {1, 2})
v + Vec<int>({1, 2})
答案 1 :(得分:1)
v.equals({8, 9})
怎么样?此外,虽然v + {1, 2, 3, 4}
是不可能的,但您可能仍会像许多向量矩阵实现一样重载逗号运算符(不是针对int,而是针对特定类型,如:v + (V(1), 2, 3, 4)
,如果您愿意,可以添加宏它们)。