2016-05-02 12 views
3

私は過去数日間のテンプレート変換演算子タイプの控除に関するコンパイラ間の違いに取り組んできました。スタックオーバーフローサイズ例:テンプレート化された変換演算子のタイプの差異はclangとgccで異なります

void foo(int i); 

struct any_const_reference { 
    template <typename T> 
    operator const T&(); 
}; 

template <typename T, typename Enable=void> 
struct detect_call : std::false_type { }; 

template <typename T> 
struct detect_call<T, 
    decltype(declval<T>()(any_const_reference())) 
> : std::true_type { }; 

Demo

を表現detect_call<decltype(foo)>::value、私が上で私の手を得ることができるコンパイラのいずれかのいずれかの現代版を使用して(gccの中で最新のビーイングのGCCを打ち鳴らすとfalsetrueを与えます5.2およびclang 3.8)。質問:

  • どちらが正しいですか?つまり、C++標準に準拠していますか?
  • この違いの原因は何ですか?
  • 一般的に、変換演算子(またはこのフォームの変換演算子、たとえばtemplate <typename T> operator T();)のTに適用される型減算ルールは何ですか?それらはC++標準のどこにありますか?

注:これは、この質問に似ているようだ:Template argument type deduction by conversion operator(確かに、私もその正確な違いに遭遇しました)が、私はかなりその答えと、このケースとの間のマッピングが表示されません。これがこの問題のもう一つの例である場合、この問題は、この問題をこのユースケースにどのようにマッピングするかまでです。

+3

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63217のように見えます。 –

+0

あなたはあなたのコードに完全な例を入れて、あなたがテストしているgccとclangのバージョンと、このバグを見つけた他の人が見つけやすくするために? – xaxxon

+0

@ xaxxon完全な例はデモリンクにありますが、基本的に#includeとmainには与えられた式を呼び出しています。後継のためにコンパイラのバージョンを追加しました –

答えて

4

これはちょうど、実際にfoo()を呼び出すために単純化することができる。

void foo(int) { } 

struct any_const_reference { 
    template <typename T> 
    operator const T&(); 
}; 

int main() { 
    foo(any_const_reference{}); // ok on clang 
           // error on gcc 
} 

これはgccのバグ(上記TCさんのコメントあたり#63217)です。 [temp.deduct.conv]の場合は、Tintと推測する必要があります(この場合、Pconst T&で、Aintです)。

+0

ありがとうございます。 [temp.deduct.conv]はまさに私が探していたものですが、見つけられませんでした。 –

関連する問題