Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this valid C++ 11

Tags:

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. 
like image 309
Simon Bourne Avatar asked Oct 15 '15 11:10

Simon Bourne


People also ask

Does C++11 include C11?

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.

What is the meaning of C 11?

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.

What is C++11 and C++ 99?

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++.

What came before C++11?

C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14.


1 Answers

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); 
like image 76
Barry Avatar answered Oct 13 '22 18:10

Barry