4

I have the following class definition:

template<typename T>
class Point {
  private:
    T px, py;
  public:
    Point(T x, T y): px(x), py(y) {
      std::cout << "created " << x << ":" << y <<std::endl;
    };
    T x() const { return px; };
    T y() const { return py; };
};

from which I am deriving specializations, e.g.

class PointScreen: public Point<int> {
  using Point::Point;
};

When I compile this in clang++, I get no warning / error, but the constructor is not called:

#include <iostream>
// definitions from above      
int main() {
  std::cout << PointScreen(100, 100).x() << std::endl;
  return 0;
}

This returns a random value (and also not the debug output "created..."). The value returned by e.g. x() is obviously "undefined".

I have just tried the same in g++ here, and there I obtain the expected result. Is this a problem with clang++ or have I a bug in my code?

My clang version: Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0). I compile with -std=c++11 -Wall.

fuenfundachtzig
  • 7,952
  • 13
  • 62
  • 87
  • Works with clang++3.4. [Live example](http://coliru.stacked-crooked.com/view?id=3c/19f88e687067cd) – dyp Aug 31 '13 at 21:10
  • Inheriting ctors have been implemented [in clang 3.3](http://clang.llvm.org/cxx_status.html). – dyp Aug 31 '13 at 21:12
  • Is there a way to make this code work in clang 3.0? – fuenfundachtzig Sep 01 '13 at 11:19
  • `template < typename... Args > PointScreen(Args&&... args) : Point(std::forward(args)...) {}` works as a constructor that can call all ctors of the base class (tried with with clang++3.0). Either way, you need to put make it `public` in `PointScreen`. – dyp Sep 01 '13 at 11:59
  • That template ctor doesn't take an `initializer_list` implicitly introduced via a *braced-init-list*, though (because its type isn't deduced). You'd need separate ctors for initializer-lists if using that template ctor workaround. – dyp Sep 01 '13 at 18:07

1 Answers1

1

As pointed out in the comments, you need a compiler supporting inheriting constructors. From the Apache C++11 overview you can see that this feature is only available for gcc >= 4.8 and Clang >= 3.3.

For older compilers, you have to manually define all the constructors, by calling the base constructors. See also this Q&A for more details on work-arounds.

Community
  • 1
  • 1
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • That's what I tried and failed: Could you give an example of how I redefine the constructors? – fuenfundachtzig Sep 02 '13 at 17:25
  • @fuenfundachtzig Base classes can be initialized just as a regular member in the initialization-list: `PoinScreen::PointScreen(int x, int y): Point(x, y) {}` – TemplateRex Sep 02 '13 at 17:45
  • 1
    @fuenfundachtzig [Complete live example](http://coliru.stacked-crooked.com/a/5cfc5a72cbfeb7e1) – dyp Sep 02 '13 at 17:56
  • @DyP tnx, I am on a tablet so typing an example was too cumbersome. Nice to see that the injected base class name can also be used in the initializer-list ([used to be a gcc bug](http://stackoverflow.com/q/8887864/819272)) – TemplateRex Sep 02 '13 at 18:02