重载类型转换为初始化列表

时间:2016-06-12 13:53:19

标签: c++ c++11 vector stl

我们假设我正在开发一个类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)
}

2 个答案:

答案 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),如果您愿意,可以添加宏它们)。