g ++の下でコンパイルするコードはありますが、clangではコンパイルできません。これは有効なC++ 11
2つの名前空間宣言のマージなど、さまざまな小さな方法で変更した場合、コードがコンパイルされます。
clang -fsyntax-only -std=c++11 testcase.cpp
を用いてコンパイルするG ++:
g++ -fsyntax-only -std=c++11 testcase.cpp
バージョンは、両方のUbuntuのコア15.04に、G ++ 4.9.2打ち鳴らす3.6.0ある。打ち鳴らすと共にコンパイルする
// 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);
}
}
私はこれが打ち鳴らすのバグであると考えてい
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.
フレンド関数は(クラスで宣言されていても)名前空間スコープを持っています。この場合、 'bool Root :: g()'の2つの関数宣言があります。テンプレートパラメータは宣言を変更しません。だからあなたのマイナーな変更がこのコードを動作させる理由です。実際にはg ++でコンパイルするともっと驚いています。 –
@SimonKraemerあなたは関数を複数回宣言することができます。とにかく 'friend'宣言は関数を再宣言しません。 – Barry
これは完全なコードですか、それとも関連する部分ですか? –