I struggled with the compilation problem and was able to reduce the problem to a small segment of code.
To set up the scene, I am trying to do CRTP where the base method calls another in a derived class. The complication is that I want to use return types to get the forwarding type directly to the Derived class method. This always fails to compile unless you pass a call statement in a derived class.
This compiles:
#include <utility>
struct Incomplete;
template <typename Blah>
struct Base
{
template <typename... Args>
auto entry(Args&&... args)
-> decltype(std::declval<Blah&>()(std::declval<Args&&>()...));
};
void example()
{
Base<Incomplete> derived;
}
Until this happens: (note the comment only for difference)
#include <utility>
struct Incomplete;
template <typename Blah>
struct Base
{
template <typename... Args>
auto entry(Args&&... args)
-> decltype(std::declval<Blah&>().operator()(std::declval<Args&&>()...));
};
void example()
{
Base<Incomplete> derived;
}
The error I am getting is:
<source>: In instantiation of 'struct Base<Incomplete>':
15 : <source>:15:22: required from here
10 : <source>:10:58: error: invalid use of incomplete type 'struct Incomplete'
-> decltype(std::declval<Blah&>().operator()(std::declval<Args&&>()...));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
There appears to be some special behavior when decltype resolves in the Derived class. Is there anything in the standard that could explain this?
EDIT:
PS: godbolt: https://godbolt.org/g/St2gYC