Calling friend template function with no parameter defined in class template

95 views Asked by At

I've been experimenting with calling a templated friend function with no parameter, which is defined in class template. I found no solution for the exact that case and solved my problem the other way, but during my experiments I suddenly found some interesting piece of code. It works, but I don't know why. Here's this example:

#include <iostream>

template<class T> class A
{
public:
        void test() const
        {
                std::cout << "A!" << std::endl;
        }

        template<class U> friend A fun()
        {
                return A();
        }
};

int main(int argc, char* argv[])
{
        A<double> aa; // 1
        const auto& a = fun<int>();

        a.test();

        return 0;
}

As I said, it works for me on GCC 4.8.1. If I remove (1), it fails with the following:

main.cpp: In function 'int main(int, char**)':                                                                                                                                                                     
main.cpp:20:18: error: 'fun' was not declared in this scope                                                                                                                                                        
  const auto& a = fun<int>();                                                                                                                                                                                      
                  ^                                                                                                                                                                                                
main.cpp:20:22: error: expected primary-expression before 'int'                                                                                                                                                    
  const auto& a = fun<int>();

I suspect there's UB here, but it will be very interesting if anyone could clarify:

  1. Why it at all works while I didn't tell fun() which specialization of A it should use?
  2. If it's not UB, what type is T? I tried type_info and found just that it's not neither int nor double. typeid().name() didn't help as it returns 'FdvE' for me.
1

There are 1 answers

0
Columbo On BEST ANSWER

This seems to be a GCC-bug. friend function templates that are defined in a class can only be found via ADL: GCC apparently considers aa during ADL for the call in main (for no reason) and calls A<double>'s fun, as confirmed through this static assertion:

void test() const
{
    static_assert( std::is_same<T, double>::value, "" );
}

Demo.
Clang does not compile this code at all.