Problem with C++11 template methods, friend, and namespaces

Hi,

We reported an issue when we combine template methods, friend, and
namespace in 2014 and nothing happened with the report until now (see
https://bugs.llvm.org//show_bug.cgi?id=20877). Could maybe one of the
developers confirm/deny that this is an issue or are we assuming some
incorrect C++11 code?

Best regards,

Johnny Willemsen

This does look like a valid bug, and I've put a comment in the Bugzilla
ticket. It looks like something is going wrong with the handling of
default template arguments when instantiating friend template declarations,
though where exactly in clang the bug is originating I haven't a clue.

John

Hi,

Thanks for the confirmation. We also assumed it as something valid, the
code does compile with Visual Studio 2015, gcc, and Intel C++ but we do
know that that is not a guarantee that it is valid C++. Hopefully
someone can pick this up soon and get this issue resolved.

Thanks!

Johnny

Hi Johnny:

Is this bug preventing you from compiling TAO with clang?

I don’t have a fix, but was able to create a smaller test case – perhaps it’ll help someone figure out what’s going on.

#include <type_traits>

namespace FOO {
class T_base {};
class A : public T_base {};

template struct o_r;

template <typename T,
typename = typename std::enable_if<std::is_base_of<T_base, T>::value>>
o_r make_f();

template class o_r final {
template <typename _Tp1,
typename = std::enable_if<std::is_convertible<_Tp1 *, T *>::value>>
explicit o_r(_Tp1 *) {}
public:
template <typename _Tp1, typename NOT_INFERED> friend o_r<_Tp1> make_f();
};

template <typename T, typename> o_r make_f() { return o_r(new T()); }
} // namespace FOO

void foo() {
#ifdef BAD
auto l1 = FOO::make_fFOO::A();
auto l2 = FOO::make_fFOO::A(); // << second one fails.
#else
auto l1 = FOO::make_fFOO::A();
auto l2 = FOO::make_f<FOO::A, void>();
#endif
}

local:/Users/dhinton/fail $ …/tools/3.9.0/Debug/bin/clang++ -std=c++11 -c f.cpp -DBAD
f.cpp:27:13: error: no matching function for call to ‘make_f’
auto l2 = FOO::make_fFOO::A(); // << second one fails.
^~~~~~~~~~~~~~~~~~~
f.cpp:18:67: note: candidate template ignored: couldn’t infer template argument ‘NOT_INFERED’
template <typename _Tp1, typename NOT_INFERED> friend o_r<_Tp1> make_f();
^
1 error generated.

hth…
don