Саттер, 8 задача книги "Новые сложные задачи на C++"
От: Alexey F  
Дата: 02.01.09 23:02
Оценка: 12 (1)
Здравствуйте!

В книге Герба Саттера "Новые сложные задачи на C++" (2005 год издания) в восьмой задаче ("Дружественные шаблоны") вычитал, что в g++ проблематично объявить шаблонную функцию (располагающуюся внутри чужого пространства имён) другом класса (по крайней мере, в версии 3.4; в процессе проверки выяснилось, что и используемый мной Mingw 3.4.5 страдает аналогичной проблемой, а вот Mingw 4.3.0 уже воспринимает второй предложенный Саттером вариант решения проблемы "на ура").
Суть задачи заключалась в том, что немногие компиляторы способны правильно (следуя букве стандарта) прочитать объявление другом класса шаблонной функции внутри чужого пространства имён (далее пример):

namespace Some {
    template<class T>
    void func ( T* ptr ) {
        // ...
        delete ptr;
    }
}

class Test {
    ~Test (); // Естественно, private

    // Ошибка компиляции будет здесь у множества компиляторов:
    friend void Some::func ( Test* ); 

    // Эти строки понимают уже многие (но увы, не g++ 3.4.*):
    friend void Some::func<Test> ( Test* );
    // или:
    friend void Some::func<> ( Test* );
};


Как я понял из текста этой главы (задачи), Саттер не предложил способа решения этой проблемы для g++ (кроме как избавиться от обрамляющего функцию пространства имён или создать внутри пространства имён дополнительные классы (если я не прав, прошу поправить)). Немного помучавшись, нашёл вариант кода, устраивающий как (Mingw) g++ 3.4.*/g++ 4.3.0, так и, как впоследствии выяснилось, MS VC++ 2005 Express Edition:

namespace Some {
    template<class T>
    void func ( T* ptr ) {
        // ...
        delete ptr;
    }
}

class Test {
    ~Test () {}

    template<class T>
    friend void Some::func ( T* );
};


Однако, некоторые из протестированных мной компиляторов (Borland’вский и MS VC++ 6.0) отказались принимать такой код.

Теперь, собственно, вопрос:
"изобретённый" мной способ не противоречит стандарту? Может, эта проблема уже давно решена более красивым способом, не вызывающим нареканий вообще ни у одного компилятора? Если да, можно на него (на способ ) взглянуть?

P.S. Мои извинения, если я буду отвечать очень долго.
P.P.S. Вопрос задан из чистого любопытства и тяги к знаниям, ни в одном проекте конструкцию пока не применял
P.P.P.S. Не смог воспользоваться поиском: :

Поисковая система занята или временно недоступна.
DBG> errCode: 103

саттер новые сложные задачи на c++ восьмая задача g++ 3.4 friend template
Re: Саттер, 8 задача книги "Новые сложные задачи на C++"
От: rg45 СССР  
Дата: 03.01.09 10:47
Оценка: 4 (1)
Здравствуйте, Alexey F, Вы писали:

AF>Здравствуйте!


AF>В книге Герба Саттера "Новые сложные задачи на C++" (2005 год издания) в восьмой задаче ("Дружественные шаблоны") вычитал, что в g++ проблематично объявить шаблонную функцию (располагающуюся внутри чужого пространства имён) другом класса (по крайней мере, в версии 3.4; в процессе проверки выяснилось, что и используемый мной Mingw 3.4.5 страдает аналогичной проблемой, а вот Mingw 4.3.0 уже воспринимает второй предложенный Саттером вариант решения проблемы "на ура").

AF>...

Visual'ы, начиная с 7.1, также компилируют эти варианты без проблем с единственным исключением — MSVC 7.1 отказывается понимать friend void Some::func(Test*).

AF>
AF>class Test {
AF>    ~Test () {}

AF>    template<class T>
AF>    friend void Some::func ( T* );
AF>};
AF>


AF>Теперь, собственно, вопрос:

AF>"изобретённый" мной способ не противоречит стандарту? Может, эта проблема уже давно решена более красивым способом, не вызывающим нареканий вообще ни у одного компилятора? Если да, можно на него (на способ ) взглянуть?

Такое объявление дружественности абсолютно законно. Но оно имеет несколько отличающийся эффект: дружественными объявляются ВСЕ инстанцированные варианты шаблонной функции Some::func, тогда как по задумке хотелось бы объявить другом только один конкретный вариант.

AF>P.P.S. Вопрос задан из чистого любопытства и тяги к знаниям, ни в одном проекте конструкцию пока не применял


Самое интересное: что принуждает (или может принудить) нас адаптировать код под старые, далекие от стандарта компиляторы. Конечно, иногда таки приходится. Иногда это даже интересно. Но, если глобально, лучше побыстрее отойти от этих компиляторов, и не тратить зря время.
--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.