Note that there are some explanatory texts on larger screens.

plurals
  1. POCRTP-related compiler error on pointer-to-a-member-function default value
    text
    copied!<p> Hi there,</p> <p>While making a CRTP-based generic wrapper to call arbitrary library functions, I've encountered a problem which I have trouble understanding. Here is a very simplified code to illustrate the problem:</p> <pre class="lang-c++ prettyprint-override"><code>#include &lt;iostream&gt; template&lt; typename PValue, typename PDerived &gt; class TBase { private: typedef TBase TSelf_; typedef PDerived TDerived_; protected: typedef PValue TValue_; protected: TBase( void ) { std::cout &lt;&lt; " TBase::TBase() " &lt;&lt; std::endl; } public: void Foo( void ) { std::cout &lt;&lt; " TBase::Foo() " &lt;&lt; std::endl; } template&lt; typename PType &gt; static void Call( PType /*pSomething*/, void(TDerived_::*pFunction)( void ) = &amp;TSelf_::Foo, TDerived_ pDerived = TDerived_() ) { ( pDerived.*pFunction )(); std::cout &lt;&lt; " static TBase::Call(). " &lt;&lt; std::endl; } }; template&lt; typename PValue &gt; class TDerived : public TBase&lt; PValue, TDerived&lt; PValue &gt; &gt; { friend class TBase&lt; PValue, TDerived&lt; PValue &gt; &gt; ; private: typedef TBase&lt; PValue, TDerived &gt; TBase_; typedef TDerived TSelf_; public: TDerived( void ) : TBase_() { std::cout &lt;&lt; " TDerived::TDerived() " &lt;&lt; std::endl; } void Foo( void ) { std::cout &lt;&lt; " TDerived::Foo() " &lt;&lt; std::endl; } void Bar( void ) { std::cout &lt;&lt; " TDerived::Bar() " &lt;&lt; std::endl; } }; int main( void ) { TDerived&lt; int &gt;::Call( 1 ); TDerived&lt; int &gt;::Call( 1, &amp;TDerived&lt; int &gt;::Foo ); TDerived&lt; int &gt;::Call( 1, &amp;TDerived&lt; int &gt;::Bar, TDerived&lt; int &gt; () ); return ( 0 ); } </code></pre> <p>Everything compiles and works as intended. However, if I try to use pointer to <code>TDerived::Foo()</code> as a default argument for the second parameter in <code>TBase::Call(...)</code>:</p> <pre class="lang-c++ prettyprint-override"><code>static void Call( PType /*pSomething*/, void(TDerived_::*pFunction)( void ) = &amp;TDerived_::Foo, TDerived_ pDerived = TDerived_() ) </code></pre> <p>compilers gives a syntax error... I have a feeling it is related to how compiler parses code and that it cannot figure out pointer to a function of yet to be defined (or instantiated) class. However, it has no problem calling <code>TDerived</code> constructor as a default argument for the third parameter of <code>TBase::Call(...)</code>. Can someone give me a definite answer about what's going on? Why derived class MFP is not accepted, and object of derived class is accepted as default arguments?</p> <p>Thanks.</p> <p>EDIT: compiler's error (MSVS2010 command line compiler):</p> <pre class="lang-c++ prettyprint-override"><code>FMain.cpp(224) : error C2061: syntax error : identifier 'TDerived_'; FMain.cpp(233) : see reference to class template instantiation 'TBase&lt;PValue,PDerived&gt; with [PValue=int,PDerived=TDerived&lt;int&gt;]' being compiled; FMain.cpp(323) : see reference to class template instantiation 'TDerived&lt;PValue&gt; with [PValue=int]' being compiled </code></pre> <p>It's a syntax error - it does not recognize <code>TDerived_</code> as type in default argument for MFP. There are other errors following this one, they are all syntax errors, since function definition is ill-formed now. That is how I understand it.</p> <p>EDIT: Basically, I don't understand why can I use an object of <code>TDerived_</code> as a default argument, but can not use a pointer to a member function as a default argument.</p> <p>EDIT: Ok, this is driving me crazy now. First of all, I changed to <code>typedef TBase&lt; PValue, TDerived &gt; TBase_;</code> as it was pointed out (thank you, guys!). Indeed, it only compiled under MSVC++, since this compiler does not do two-part parsing; i.e., on codepad.org (which uses g++ 4.1.2) it didn't compile. Second, after that, I tried to use <code>static void Call( PType /*pSomething*/, void(TDerived_::*pFunction)( void ) = &amp;TDerived_::Foo, TDerived_ pDerived = TDerived_() )</code> on codepad.org and... it compiled and run correctly! So I'm REALLY confused now: people explained to me why it's not correct (and I couldn't understand "why" (see my previous EDIT)) and now it turns out g++ compiles it correctly... Does it mean it just MSVC++ problem and not the code? Or code does have a problem from the Standard point of view (and I cannot see it) and g++ accept it "by mistake" (unlikely, I think)?.. Help?!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload