Search code examples
classc++11returninitializer-list

Default values when returning a class via initializer list (vs2015 vs vs2017)


I'm looking for an explanation of the following observation. Starting from vs2017 the code in question in short reads as:

#include <iostream>

class Range
{
public:
  double min = 0; // some default values here
  double max = 1;

  double getRange() const {return max-min;};
};

Range makeRange(double a, double b)
{
  return {a,b}; // the initializer list return in question
}

int main()
{
  const auto x = makeRange(4.0,5.0); // some example application
  std::cout << x.min << ", " << x.max << std::endl;
}

in this, the class Range provides default values for "min" and "max" and can be initialized by the initializer list from "makeRange". This code compiles and works in VS2017.

In VS2015 it does not compile (error C2440: 'return': cannot convert from 'initializer list' to 'Range'). However, if the default values are removed such that

class Range
{
public:
  double min;
  double max;

  double getRange() const {return max-min;};
};

it compiles and works in vs2015. It will still compile in VS2017. However, the default values are undefined (i guess). Once a constructor is added such that there are default values

  Range():min(0),max(0){};

the compilation in VS2017 fails. So there are two questions about this:

  1. I assumed VS2015 supported initializer lists. Why does the first code not compile in VS2015? Why does it when the defaults are removed?
  2. Why does the definition of a default constructor destroy the initializer list functionality in VS2017? Settings the defaults at the members themselves obviously worked.

Solution

  • You are using aggregate initialization. This of course requires Range to be an aggregate type. The definition of aggregate has been tweaked a lot between different versions of the standard.

    Thus, in C++11 a class with default member initializers couldn't be an aggregate, but starting with C++14 it can be. It appears that VS2015 uses the former definition and VS2017 the latter.

    A class with user-provided constructors is not an aggregate in any version of the standard.