I have the following code that compiles under g++, but not with clang.
Clang will compile the code if changed in various minor ways, such as merging the 2 namespace declarations.
// The problem disappears without namespaces. namespace Root { // The problem disappears if 'g' is in the global namespace, and we change // the friend declaration to '::g' // The problem disappears if 'g' has void return type. // The problem disappears if we get rid of the 'Value' template argument // and the 'value' parameter. template<typename Value, typename Defaulted = void> bool g(Value value); // The problem disappears if MyClass is not a template. template<typename ClassValue> class MyClass { private: template<typename Value, typename Defaulted> friend bool g(Value value); }; } // The problem disappears if we declare the Root namespace in a single block // containing 'g', 'MyClass' and 'f'. // The problem remains if we declare f in the global namespace and reference // Root::g. namespace Root { void f() { MyClass<int> value; g(value); } }
To compile with clang:
clang -fsyntax-only -std=c++11 testcase.cpp
To compile with g++:
g++ -fsyntax-only -std=c++11 testcase.cpp
Versions are g++ 4.9.2, clang 3.6.0, both on Ubuntu core 15.04.
Clang gives the error message:
testcase.cpp:24:9: error: no matching function for call to 'g' g(value); ^ testcase.cpp:14:21: note: candidate template ignored: couldn't infer template argument 'Defaulted' friend bool g(Value value); ^ 1 error generated.
No, C++11 does not support ALL the features of C11. It does not even support all the features of C99. Variable-length arrays, for example, were introduced in C99, but C++ does not yet support them.
A synthetic amino acid radiolabeled with carbon-11. Acting as a methyl donor, methionine C 11 is incorporated into macromolecules, where it serves as a positron emission tomography (PET) imaging agent for detecting tumors with high rates of protein synthesis.
C99 does not allow flexible array member initialization (it's a GNU extension). C++11 has uniform initialization, which is similar to compound literals: return {cos(angle)*r,sin(angle)*r}; . anonymous unions are valid C++.
C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14.
I believe this is a clang bug. From [temp.param], we have:
If a friend function template declaration specifies a default template-argument, that declaration shall be a definition and shall be the only declaration of the function template in the translation unit.
The set of default template-arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are (8.3.6).
The latter point means that we can write:
template <typename T, typename U=int> void h(); template <typename T, typename U> void h() { } h<int>();
And this is perfectly well formed code that clang compiles. We cannot specify the default template-argument to g
based on the rule quoted, as g
is previously declared, but not specifying it should still keep Defaulted
available for use as void
via the merge step. If the default-argument is available, then lookup should be able to find the g
we want.
A workaround would be to simply friend the specialization we care about:
friend bool g<>(MyClass value);
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