为什么我不能使用括号括起的列表作为重载运算符的操作数?

时间:2017-02-12 18:41:40

标签: c++ c++11 operator-overloading language-lawyer initializer-list

我正在使用一组自定义C ++库,它们提供表示序列的类型。有一个重载operator+,它接收两个序列并连接它们,一个初始化器接受一个std::intializer_list,可以用来用值列表初始化序列。这些功能中的每一个都可以很好地运行,但由于某些原因,它们不能很好地协同工作。

这是reduced test case that shows off the issue

#include <iostream>
#include <initializer_list>
using namespace std;

struct InitListConstructible {
    InitListConstructible() = default;

    InitListConstructible(std::initializer_list<int> elems) {
        // do something
    }
};

InitListConstructible operator+ (InitListConstructible lhs,
                                 InitListConstructible rhs) {
    return {};                                  
}

int main() {
    /* Totally fine - use initializer list constructor. */
    InitListConstructible lhs = { 1, 2, 3 };

    /* Totally fine - use overloaded + operator. */
    auto legit = lhs + lhs;

    /* Totally fine - second argument constructed from initializer list. */
    freeFunction(lhs, { 1, 2, 3 });

    /* Totally fine - explicit call to operator+. */
    auto alsoLegit = operator+ (lhs, { 1, 2, 3 });

    /* Not okay - reports error about expected primary-expression. */
    auto error = lhs + { 1, 2, 3 };

    return 0;
}

这里,类型InitListConstructible是一个简单的结构,它有一个默认的构造函数和一个初始化列表构造函数。还有一个重载的+运算符,它接收两个InitListConstructible个对象并返回第三个。

main中,我可以看到初始化列表构造函数工作得很好,重载的+运算符也是如此。它完全合法地调用一个函数,它接受两个InitListConstructible s,其中第二个从括号括起的表达式初始化。

然而,行

auto error = lhs + { 1, 2, 3 };

无法编译,并报告有关缺少的primary-expression的错误。这让我相信语言语法不允许这样的事情。

我的问题如下:

  1. 我对问题的分析 - 语言规范只是不允许在表达式上下文中使用大括号括起来的列表 - 对吗?
  2. 是否有一个根本原因,为什么不允许这样做,因为括号括起的表达式的类型可以从operator+的参数类型推导出来?我怀疑这与C ++中的每个表达都需要具有不依赖于上下文的明确定义的类型这一事实有关,如果这是正确的我会感激确认

0 个答案:

没有答案
相关问题