Чего-то я не понимаю в шаблонах.
От: K13 http://akvis.com
Дата: 08.09.15 08:33
Оценка:
Код много лет живет под MSVC разных версий (с 2005 по 2013) и эппловским форком g++
Но вот поставил на новом маке свежий XCode, и счастье кончилось.

Привожу краткую выжимку проблемы:

class PP {};

template <class A, class P=PP>
class BP : public P
{
public:
    void process()
    {
        This()->iterate();
    }
    
protected:
    A* This()
    {
        return static_cast<A*>( this );
    }
};

template <class A, class P=PP>
class SP : public BP<A,P>
{
    typedef BP<A> Inherited;
    
public:
    void iterate()
    {
        Inherited::This()->processElement( 0 );
    }
};

template <class A, class P=PP>
class CP : public BP<A,P>
{
    typedef BP<A> Inherited;
    
public:
    template<bool B>
    void processElement( int idx ) { /*not implemented*/ }
    
    void iterate()
    {
        A *t = Inherited::This();
        t->processElement<true>( 0 );
        t->processElement<false>( 0 );
    }

};

class TS : public SP<TS,PP>
{
public:
    void processElement( int idx )
    {
    }
};

class TC : public CP<TC,PP>
{
public:
    template<bool B>
    void processElement( int idx )
    {
        if ( B )
        {
        }
        else
        {
        }
    }
};


void test()
{
    TS testS;
    testS.process();
    TC testC;
    testC.process();
}


Mac-mini-Ivan:pub korsar$ g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
Mac-mini-Ivan:pub korsar$ g++ -c t01.cpp
t01.cpp:43:6: error: reference to non-static member function must be called
                t->processElement<true>( 0 );
                ~~~^~~~~~~~~~~~~~
t01.cpp:9:11: note: in instantiation of member function 'CP<TC, PP>::iterate' requested here
                This()->iterate();
                        ^
t01.cpp:78:8: note: in instantiation of member function 'BP<TC, PP>::process' requested here
        testC.process();
              ^
t01.cpp:61:7: note: possible target for call
        void processElement( int idx )
             ^
t01.cpp:44:6: error: reference to non-static member function must be called
                t->processElement<false>( 0 );
                ~~~^~~~~~~~~~~~~~
t01.cpp:61:7: note: possible target for call
        void processElement( int idx )
             ^
2 errors generated.


Больше всего восхищает, что в качестве "возможного кандидата" выдается именно то что мне нужно — шаблонная processElement в классе TC.

При этом старый компилятор ничего плохого не видит:
macbuild:pub macbuild$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

macbuild:pub macbuild$ g++ -c t01.cpp
macbuild:pub macbuild$


Спрашивается в задачнике -- это более строгое соответствие стандарту со стороны clang, глюк у них или я сам туплю со страшной силой?
И если верна первая причина -- то как это переформулировать более правильно?
Учитывая, что в сложном случае (TC) processElement должна быть темплейтной -- практически всегда внутри нее сидят шаблонные хелперовские функции/методы параметризованные тем же bool.
Re: Чего-то я не понимаю в шаблонах.
От: K13 http://akvis.com
Дата: 08.09.15 08:37
Оценка:
проверил на rextester — как и у меня, gcc и vc компилируют, clang отказывается.
Re[2]: Чего-то я не понимаю в шаблонах.
От: Chorkov Россия  
Дата: 08.09.15 09:06
Оценка: 6 (1) +2
Здравствуйте, K13, Вы писали:

K13>проверил на rextester — как и у меня, gcc и vc компилируют, clang отказывается.


template <class A, class P=PP>
class CP : public BP<A,P>
{
    typedef BP<A> Inherited;
    
public:
    template<bool B>
    void processElement( int idx ) { /*not implemented*/ }
    
    void iterate()
    {
        A *t = Inherited::This();
        t-> template processElement<true>( 0 );
        t-> template processElement<false>( 0 );
    }

};
Re[3]: Чего-то я не понимаю в шаблонах.
От: ArtDenis Россия  
Дата: 08.09.15 09:59
Оценка:
Здравствуйте, Chorkov, Вы писали:

K13>>проверил на rextester — как и у меня, gcc и vc компилируют, clang отказывается.


C>
C>        t->> template processElement<false>( 0 );
C>


Странно что gcc без template скомпилировал.
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: Чего-то я не понимаю в шаблонах.
От: Mr.Delphist  
Дата: 08.09.15 10:15
Оценка: +1
Здравствуйте, ArtDenis, Вы писали:

AD>Здравствуйте, Chorkov, Вы писали:


K13>>>проверил на rextester — как и у меня, gcc и vc компилируют, clang отказывается.


C>>
C>>        t->> template processElement<false>( 0 );
C>>


AD>Странно что gcc без template скомпилировал.


Ничего странного — с ростом сложности Стандарта компиляторы всё больше напоминают браузеры: вроде бы везде один и тот же JavaScript+CSS, но везде свои особенности.
Re: Чего-то я не понимаю в шаблонах.
От: Кодт Россия  
Дата: 08.09.15 13:15
Оценка: +1
Здравствуйте, K13, Вы писали:

Прежде всего, бросается в глаза

K13>template <class A, class P=PP>
K13>class SP : public BP<A,P>
K13>{
K13>    typedef BP<A> Inherited;
        typedef BP<A,P> Inherited;
K13>};

K13>template <class A, class P=PP>
K13>class CP : public BP<A,P>
K13>{
K13>    typedef BP<A> Inherited;
        typedef BP<A,P> Inherited;
K13>};


А является ли это причиной ошибки — щас посмотрю.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.