Код много лет живет под 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.
проверил на rextester — как и у меня, gcc и vc компилируют, clang отказывается.
Здравствуйте, 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 );
}
};
Здравствуйте, Chorkov, Вы писали:
K13>>проверил на rextester — как и у меня, gcc и vc компилируют, clang отказывается.
C>C> t->> template processElement<false>( 0 );
C>
Странно что gcc без template скомпилировал.
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, Chorkov, Вы писали:
K13>>>проверил на rextester — как и у меня, gcc и vc компилируют, clang отказывается.
C>>C>> t->> template processElement<false>( 0 );
C>>
AD>Странно что gcc без template скомпилировал.
Ничего странного — с ростом сложности Стандарта компиляторы всё больше напоминают браузеры: вроде бы везде один и тот же JavaScript+CSS, но везде свои особенности.
Здравствуйте, 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>};
А является ли это причиной ошибки — щас посмотрю.