2015-10-07 4 views
5

Я пытаюсь публично вывести класс из шаблона, который сделает его наследуемым от базового класса и получит доступ к защищенным членам. Но до того, как шаблон расширится, он не имеет таких прав, поэтому он не может использовать элемент базы в качестве параметра шаблона:Доступ к базовому классу шаблона до расширения шаблона, полученного из

using Fun = void (*)(); 

class Base { 
protected: 
    // friend class Derived; // ...need this to eliminate complaint 
    static void something(); 
}; 

template<Fun F> 
class Variant : public Base {}; 

class Derived : public Variant<&Base::something> { // `something()` is protected 
public: 
    void somethingElse() { 
     something(); // doesn't complain about this `something()` 
    } 
}; 

int main() {} 

Странная немного об этом для меня было то, friending это работало на всех. Интересно, если я мог бы «украдкой Производная в дверь», поместив публичное виртуальное наследование от базы до Variant:

class Derived : public virtual Base, public Variant<&Base::something> 

Это не помогло.

Вопрос: Есть ли какой-нибудь другой трюк, чтобы избежать явного упоминания всех производных классов в базе, но все же у вас есть доступ к защищенным членам из него для параметров шаблона?

(Примечание:.. Попытка это на старом GCC, 4.6.3, похоже, даже friending не помогает в этом случае Таким образом, кажется, что поддержка несколько новых)

+3

Связанный: [CWG 372] (http://wg21.cmeerw.net/cwg/issue372) и [CWG 580] (http://wg21.cmeerw.net/cwg/issue580). Кажется, что даже текущие версии clang ++ и g ++ не реализуют предлагаемое разрешение для последнего дефекта. – dyp

+0

@dyp Я думаю, что это, вероятно, «ответ» или как можно ближе. Хотите сделать это? – HostileFork

ответ

1

Наклейте нарушая доступ к метафору. Вывести класс метафонов из базы.

template<typename B> 
struct something_variant : public B { 
    typedef Variant< & B::something > type; 
}; 

class Derived : public something_variant<Base>::type { 
    … 

http://coliru.stacked-crooked.com/a/6bca00455bd3daca

Относительно CWG 372, критический текст в разрешении заключается в следующем:

[А] проверка ступа базовых спецификаторов не должно быть отложено до тех пор всей базовой specifier- список был замечен.

Это было уже принято на C++ 11, поэтому интересно, что ваш пример отклонен. И, plugging соответствующий код примера из стандарта C++ 11 в недавние Clang и GCC демонстрирует, что они просто не реализовали отсрочку. Это, по крайней мере, немного неудивительно, так как для реализации требуется некоторая структура данных для представления набора отложенных проверок доступа ... достаточно высокие усилия для краевого дела.

Смежные вопросы