6

Could someone please help me understand why the following code does not compile (g++ 4.8). My understanding is that one could initialize a POD

#include <iostream>
#include <type_traits>

struct my_int
{
  int val_;
};
struct B : public my_int
{
};

int main()
{
  std::cout << std::is_pod<my_int>::value << std::endl;
  std::cout << std::is_pod<B>::value << std::endl;
  const my_int v = { 123 };
  //const B v2 = { 123 }; // does not compile with g++ 4.8.

  return 0;
}

Compilation is:

g++ -std=c++11 t.cxx
t.cxx: In function 'int main()':
t.cxx:24:21: error: could not convert '{123}' from '<brace-enclosed initializer list>' to 'const B'
   const B v = { 123 };
                     ^

EDIT:

Thanks to everyone answer I now understand the concept of aggregate initialisation. I missed the fact that aggregate could not have base class. Therefore my current implementation plans needs to be changed. I wanted to do something like:

template < typename T >
struct base_class
{
  int val_;
};
struct MyInt : public base_class<int>
{
  void Func1() {}
};
struct MyDouble : public base_class<double>
{
  void Func2() {}
};

I'll rework the above code to avoid the use of subclass to introduce special member functions, while avoid code duplication.

Jonas
  • 121,568
  • 97
  • 310
  • 388
malat
  • 12,152
  • 13
  • 89
  • 158
  • You could add a non-trivial **non-default** ctor like `B::B(int p) : my_int(p) {}` which retains `B`'s status as a POD but allows the initialization `const B v2 = {123};`. – dyp Sep 20 '13 at 19:16

1 Answers1

6

Disclaimer

Take the following with a grain of salt as it is my interpretation of things. I am by no means an expert. (Also I have some doubts about the aggregate - initializer list relation which I stated here.)

Answer

As far as I can tell this is not possible because the aggregate initialization of v2 would be applied to the non aggregate class type B.

From this answer you can take that aggregates must not have a base class, which makes B a non aggregate and therefore not initializable by a brace enclosed initializer list.

On the other hand std::is_pod might not do what you think it does because the POD definition has changed in C++11. Therefore, it does not give you a hint if the type that is a POD can be initialized with such an aggregate initializer.

Addition

I am mainly discussing aggregate initialization here, but the more general term for this is list initialization which is less restrictive. However, checking all the cases I found in the linked resource there is no possibility to do list initialization either because (following the resource's list of effects of an initializer list):

  • the initializer list is not empty
  • B is not an aggregate
  • B is not a specialization of std::initializer_list
  • B has no
    • constructor taking an initializer list
    • constructor fitting the signature of the list
  • B is no reference type
  • B cannot be copy-initialized from 123 and not direct-initialized because there is no constructor taking an int
  • B is not value-initialized because the initializer list ist not empty
Community
  • 1
  • 1
  • Visual C++ 2013 RC backs up your theory: Microsoft (R) C/C++ Optimizing Compiler Version 17.00.60610.1 for x64 Copyright (C) Microsoft Corporation. All rights reserved. test.cpp test.cpp(18) : error C2552: 'v2' : non-aggregates cannot be initialized with ini tializer list 'B' : Types with a base are not aggregate – jschroedl Sep 20 '13 at 18:04
  • @jschroedl: clang 3.3 said something similar (`non-aggregate type 'const B' cannot be initialized with an initializer list `)but I dislike using compiler outputs for the reasoning, because they may deviate from the standard. – Nobody moving away from SE Sep 20 '13 at 18:13
  • Maybe you should link to the [C++11 answer](http://stackoverflow.com/a/7189821/420683) to the same question instead for a definition of aggregates. Besides that, I agree that with your analysis of the Standard ([dcl.init.list]/3). `const my_int v = { 123 };` is list-initialization, but it does not do (resolve to) aggregate-initialization because `my_int` is not an aggregate. The only available ctor are the default ctor and copy/move ctor, but those cannot be used with an argument of type `int`. The object to be initialized is of class type and no reference. Ergo the program is ill-formed. – dyp Sep 20 '13 at 19:13
  • @DyP: Thanks for the link (I changed it in my answer, I should have scrolled further down :). The point I was trying to make was that the OP was apparently trying to do aggregate initialization which is not possible here. Then I realized that it might be possible by list initialization and wrote the addition to rule that one out too. – Nobody moving away from SE Sep 20 '13 at 19:26