1

I am currently doing an upgrade from gcc 4.9 (c++1) to gcc 8.2 (c++14) and I have an issue on gcc 8.2 with the following code

#include <type_traits>
#include <iostream>

template <class T>
struct has_foo_method 
{
   struct not_found {};

   template <class C>
   static auto f(C* e) -> decltype(foo(*e));

   template <class>
   static auto f(...) -> not_found;

   using type = decltype(f<T>(nullptr));
   static const bool value = !std::is_same<not_found, type>::value;
};

template <class E, class E00 = std::decay_t<E>>
std::enable_if_t<!has_foo_method<E00>::value, typename has_foo_method<E00>::type>
foo(E&& e)
{
    return foo(std::forward<E>(e));
}

struct toto
{};

int main()
{
    std::cout << "same type : "<< (std::is_same<toto, std::decay<toto>::type>::value ? "TRUE" : "FALSE") << std::endl;
    std::cout << "foo methode  : " << (has_foo_method<toto>::value ? "TRUE" : "FALSE") << std::endl;
    std::cout << "foo methode for decay: " << (has_foo_method<std::decay_t<toto>>::value ? "TRUE" : "FALSE") << std::endl;
    foo(toto{});
    return 0;
}

The error is the following :

source>: In substitution of 'template<class E, class E00> std::enable_if_t<(! has_foo_method<E00>::value), typename has_foo_method<E00>::type> foo(E&&) [with E = toto&; E00 = <missing>]':
...
<source>:19:20: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)

You can find the code and error here

I also found that if I remove E00 = std::decay_t and replace E00 per E like this :

template <class E>
std::enable_if_t<!has_foo_method<E>::value, typename has_foo_method<E>::type>

the code is compiling but I can't understand why.

Do you know why it's not compiling on gcc 8.2 and it is on gcc 4.9?

chapuilo
  • 31
  • 2
  • There seems to be some circular dependency. When you call `foo(toto{});`, `foo` must be instantiated. This tries to instantiate `has_foo_method` (within `enable_if_t`), which evaluates `decltype(foo(*e));`. Which, again, tries to instantiate `foo`. And so on... – Daniel Langr Oct 02 '19 at 12:01
  • Yes I do understand that but I can't understand why it is working without `std::decay_t`. It works if I use `E00 = toto` – chapuilo Oct 03 '19 at 10:05

0 Answers0