Наследование конструктора в шаблонном классе (C++11)

У меня есть следующее определение класса:

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; };
};

из которых я получаю специализации, например.

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

Когда я компилирую это в clang++, я не получаю предупреждения/ошибки, но конструктор не вызывается:

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

Это возвращает случайное значение (а также не вывод отладки «создано...»). Значение, возвращаемое, например. x() явно "не определено".

Я только что попробовал то же самое в g++ здесь и получил ожидаемый результат. Это проблема с clang++ или это ошибка в моем коде?

Моя версия clang: Ubuntu clang версии 3.0-6ubuntu3 (tags/RELEASE_30/final) (на основе LLVM 3.0). Я компилирую с -std=c++11 -Wall.


person fuenfundachtzig    schedule 31.08.2013    source источник
comment
Работает с clang++3.4. Живой пример   -  person dyp    schedule 01.09.2013
comment
Наследование ctor было реализовано в clang 3.3.   -  person dyp    schedule 01.09.2013
comment
Есть ли способ заставить этот код работать в clang 3.0?   -  person fuenfundachtzig    schedule 01.09.2013
comment
template < typename... Args > PointScreen(Args&&... args) : Point(std::forward<Args>(args)...) {} работает как конструктор, который может вызывать все ctors базового класса (пробовали с clang++3.0). В любом случае вам нужно поставить make it public в PointScreen.   -  person dyp    schedule 01.09.2013
comment
Тем не менее, этот ctor шаблона не принимает initializer_list, неявно введенный через braced-init-list (поскольку его тип не выводится). Вам понадобятся отдельные ctors для списков инициализаторов, если вы используете обходной путь ctor шаблона.   -  person dyp    schedule 01.09.2013


Ответы (1)


Как указано в комментариях, вам нужен компилятор, поддерживающий наследование конструкторов. Из обзора Apache C++11 видно, что эта функция доступна только для gcc >= 4.8 и Clang >= 3.3.

Для более старых компиляторов вам необходимо вручную определить все конструкторы, вызвав базовые конструкторы. См. также эти вопросы и ответы для получения дополнительной информации об обходных решениях.

person TemplateRex    schedule 01.09.2013
comment
Это то, что я пытался и потерпел неудачу: не могли бы вы привести пример того, как я переопределяю конструкторы? - person fuenfundachtzig; 02.09.2013
comment
@fuenfundachtzig Базовые классы могут быть инициализированы как обычные члены в списке инициализации: PoinScreen::PointScreen(int x, int y): Point<int>(x, y) {} - person TemplateRex; 02.09.2013
comment
@fuenfundachtzig Полный живой пример - person dyp; 02.09.2013
comment
@DyP tnx, я работаю на планшете, поэтому набирать пример было слишком громоздко. Приятно видеть, что введенное имя базового класса также можно использовать в списке инициализаторов (используется для ошибки gcc) - person TemplateRex; 02.09.2013