7

I'm working with a set of custom C++ libraries that provides a type representing a sequence. There's an overloaded operator+ that takes in two sequences and concatenates them, and an initializer taking in a std::intializer_list that can be used to initialize the sequence with a list of values. Each of these functions works well on its own, but for some reason they don't play well together.

Here's a 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;
}

Here, the type InitListConstructible is a simple struct that has a default constructor and an initializer list constructor. There is also an overloaded + operator that takes in two InitListConstructible objects and returns a third.

In main, I can see that the initializer list constructor works just great, as does the overloaded + operator. It's completely legit call a function that takes in two InitListConstructibles where the second is initialized from a brace-enclosed expression.

However, the line

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

does not compile, and it reports an error about a missing primary-expression. This leads me to believe that the language syntax just doesn't allow for things like this.

My questions are as follows:

  1. Is my analysis of the issue - that the language spec just doesn't allow brace-enclosed lists in expression contexts - correct?
  2. Is there a fundamental reason why this isn't permitted, given that the brace-enclosed expression could have its type deduced from the type of the argument to operator+? My suspicion is that this has to do with the fact that every expression in C++ needs to have a well-defined type that doesn't depend on context, and if that's correct I'd appreciate a confirmation.
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 3
    Brace-init list is not an expression. There are specific places in the grammar where it may appear (e.g. as an argument in a function call; as part of `return` statement) - in the middle of an expression after `+` sign is not one of those places. – Igor Tandetnik Feb 12 '17 at 18:46
  • @IgorTandetnik That's what I suspected. Thanks for the confirmation! – templatetypedef Feb 12 '17 at 18:48

0 Answers0