<div class="gmail_quote">On Sat, Jul 14, 2012 at 11:40 PM, Rich E <span dir="ltr"><<a href="mailto:reakinator@gmail.com" target="_blank">reakinator@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi all,<div><br></div><div>Can anyone explain why the following doesn't compile?</div><div><br></div><div><div>#include <functional></div><div><br></div><div>struct X{</div><div><span style="white-space:pre-wrap">   </span>typedef std::function<void(X&)> callback_type;</div>

<div><span style="white-space:pre-wrap">  </span>virtual ~X() {}</div><div>private:</div><div><span style="white-space:pre-wrap">   </span>callback_type _cb;</div><div>};</div><div><br></div>
<div>int main(){}</div></div><div><br></div><div><br></div><div>If you comment out the virtual destructor, the code compiles fine.  Full error report:</div><div><br></div><div><br></div><div>################################################</div>

<div>







<p>CompileC build/test_function_callback.build/Debug/test_function_callback.build/Objects-normal/x86_64/main.o test_function_callback/main.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler</p>
<p>    cd /Volumes/ssd/code/sandbox/test_function_callback</p>
<p>    setenv LANG en_US.US-ASCII</p>
<p>    /Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x c++ -arch x86_64 -fmessage-length=0 -std=gnu++11 -stdlib=libc++ -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wreturn-type -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wformat -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-sign-compare -Wshorten-64-to-32 -Wno-newline-eof -Wc++11-extensions -DDEBUG=1 -isysroot /Applications/Xcode45-DP2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk -fasm-blocks -Wdeprecated-declarations -Winvalid-offsetof -mmacosx-version-min=10.7 -g -fvisibility-inlines-hidden -Wno-sign-conversion -iquote /Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/test_function_callback-generated-files.hmap -I/Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/test_function_callback-own-target-headers.hmap -I/Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/test_function_callback-all-target-headers.hmap -iquote /Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/test_function_callback-project-headers.hmap -I/Volumes/ssd/code/sandbox/test_function_callback/build/Debug/include -I/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/DerivedSources/x86_64 -I/Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/DerivedSources -F/Volumes/ssd/code/sandbox/test_function_callback/build/Debug -MMD -MT dependencies -MF /Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/Objects-normal/x86_64/main.d --serialize-diagnostics /Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/Objects-normal/x86_64/main.dia -c /Volumes/ssd/code/sandbox/test_function_callback/test_function_callback/main.cpp -o /Volumes/ssd/code/sandbox/test_function_callback/build/test_function_callback.build/Debug/test_function_callback.build/Objects-normal/x86_64/main.o</p>


<p><br></p>
<p>In file included from /Volumes/ssd/code/sandbox/test_function_callback/test_function_callback/main.cpp:1:</p>
<p>In file included from /Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:462:</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/type_traits:2825:19: error: invalid application of 'sizeof' to an incomplete type 'X'</p>

<p>    static_assert(sizeof(_Tp) > 0, "Type must be complete.");</p>
<p>                  ^~~~~~~~~~~</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/type_traits:2830:15: note: in instantiation of template class 'std::__1::__check_complete<X>' requested here</p>


<p>    : private __check_complete<_Tp></p>
<p>              ^</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/type_traits:2812:15: note: in instantiation of template class 'std::__1::__check_complete<X &>' requested here</p>


<p>      private __check_complete<_T0, _Tp...></p>
<p>              ^</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/type_traits:2978:15: note: in instantiation of template class 'std::__1::__check_complete<std::__1::function<void (X &)> &, X &>' requested here</p>


<p>    : private __check_complete<_Fp, _Args...></p>
<p>              ^</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/type_traits:2989:11: note: in instantiation of template class 'std::__1::__invokable_imp<std::__1::function<void (X &)> &, X &>' requested here</p>


<p>          __invokable_imp<_Fp, _Args...>::value></p>
<p>          ^</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1115:33: note: in instantiation of template class 'std::__1::__invokable<std::__1::function<void (X &)> &, X &>' requested here</p>


<p>    template <class _Fp, bool = __invokable<_Fp&, _ArgTypes...>::value></p>
<p>                                ^</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1163:9: note: in instantiation of default argument for '__callable<std::__1::function<void (X &)> >' required here</p>


<p>        __callable<typename decay<_Fp>::type>::value,</p>
<p>        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</p>
<p>/Applications/Xcode45-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1166:7: note: while substituting deduced template arguments into function template 'operator=' [with _Fp = const std::__1::function<void (X &)> &]</p>


<p>      operator=(_Fp&&);</p>
<p>      ^</p>
<p>/Volumes/ssd/code/sandbox/test_function_callback/test_function_callback/main.cpp:3:8: note: definition of 'X' is not complete until the closing '}'</p>
<p>struct X{</p>
<p>       ^</p>
<p>1 error generated.</p></div><div>################################################</div><div><br></div><div><br></div><div><br></div><div>Please let me know if I should report this as a bug.</div></blockquote><div><br>
</div><div>What's happening is:</div><div>* We need to implicitly declare a copy assignment operator for X.</div><div>* To do that, we need to compute whether the implicitly-declared copy assignment operator takes a const or non-const argument.</div>
<div>* To do that, we need to check whether any member of the class takes a non-const argument.</div><div>* To do that, we perform overload resolution in callback_type looking for the operator= which is used to copy _cb. And that leads to the diagnostic you're seeing.</div>
<div><br></div><div>The C++ standard doesn't say that we should use overload resolution here, and that we should instead just look for any operator= in the member's class type M with a parameter type of exactly const M&, const volatile M&, or M. So that seems like a Clang bug (please do file a bug for this).</div>
<div><br></div><div>As it happens, we'd currently have to perform overload resolution to look up the member's operator= anyway, since it's needed to determine X's operator='s exception specification, but the standard is being changed so that the exception specification is computed on demand (this is core issue 1330, and we do not yet implement this part of it).</div>
<div><br></div><div>As an optimization, we defer adding the implicit members to a class if it has no virtual functions (if there are virtual functions, the implicitly-declared member might override a virtual function in a base class, so we don't perform this optimization in that case). This process isn't supposed to be able to fail, so that's safe. And that's why removing the virtual destructor makes the bug disappear.</div>
<div><br></div><div><br></div><div>I'm not sure why instantiating std::function<void(X&)>::operator= would require X to be complete -- libstdc++ does not behave that way. It's possible this is a bug in libc++, but it's also possible that the standard allows this behavior and libstdc++ is just more permissive. Hopefully Howard can help with that part.</div>
</div>