In the context of a C++14 application, I use a scheme which could be resumed as follows (minimal reproducible test):
template <class Container>
struct LocateFunctions {
auto get_it() const // <-- here is the problem
{
auto ret = typename Container::Iterator();
return ret;
}
};
template <typename T>
struct A : public LocateFunctions<A<T>> {
struct Iterator {};
};
int main() {
A<int> a;
}
This approach compiles and runs perfectly in C++14, with GCC and Clang compilers.
Now I want migrate my application to Windows and for that I'm using MinGW. Unfortunately, its latest version brings GCC 4.9 which does not compile C++14. That does not seem like a serious problem because I can rewrite the C++14 constructs in C++11. So, I rewrite the get_it()
method as follows:
typename Container::Iterator get_it() const
{
auto ret = typename Container::Iterator();
return ret;
}
Unfortunately it does no compile. Both compilers produce the following error:
error: no type named ‘Iterator’ in ‘struct A<int>’
typename Container::Iterator get_it() const
^
I also tried:
auto get_it() const -> decltype(typename Container::Iterator())
{
auto ret = typename Container::Iterator();
return ret;
}
but I get exactly the same error.
Since two compilers fail to recognize the type of return, I suppose it is impossible to determine it. But I do not really know why.
Could someone please explain me why not compile and eventually a way for refactoring in C++11 that compiles?
You're using CRTP; LocateFunctions
is instantiated with an incomplete specialization of A
(A<int>
), hence accessing that specialization's members gives the rather misleading error message ("no … named … in …" instead of "… is incomplete"). However, in your example the function temploid get_it
is only (if ever) instantiated after A<int>
is indeed defined, making the typename-specifier well-formed.
As for a workaround, try to achieve a similar effect, e.g. via
template <typename T=Container>
typename T::Iterator get_it() const
{
static_assert(std::is_same<T, Container>{}, "You ain't supposed to supply T!");
auto ret = typename T::Iterator();
return ret;
}
Demo with GCC 4.9.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With