2017-12-06 13 views
4

C++標準[temp.over.link]では、関数テンプレートの等価性の決定にコンパイラの "ヒーロー的な努力"は含まれてはならないと説明されています。テンプレートの同等性またはテンプレートの機能的同等性?

例として、C++標準では、このことを提案する:

// guaranteed to be the same 
template <int I> void f(A<I>, A<I+10>); 
template <int I> void f(A<I>, A<I+10>); 
// guaranteed to be different 
template <int I> void f(A<I>, A<I+10>); 
template <int I> void f(A<I>, A<I+11>); 
// ill-formed, no diagnostic required 
template <int I> void f(A<I>, A<I+10>); 
template <int I> void f(A<I>, A<I+1+2+3+4>); 

は、このルールはまた、以下の例のように、メタプログラミングを含む場合にも適用されますか?

template<class T> 
struct t_{ 
    using type = T; 
    }; 
//ill-formed or different? 
template<class T> T f(T); 
template<class T> typename t_<T>::type f(T); 

答えて

3

は、単純なケースで始まるのをしてみましょう:私に

template <typename T> using id = T; 

template<class T> T f(T); 
template<class T> id<T> f(T); 

これはthe relevant ruleごとに、明確に病気に形成され、ノー診断が必要です。 2つの宣言は機能的には同等ですが、テンプレートパラメータの名前を変更するだけのものではありません(考慮する必要のある依存名はありません)。より複雑なケースでは


template <typename T> struct id_t { using type = T; }; 
template <typename T> using id = typename id_t<T>::type; 

template<class T> T f(T); 
template<class T> id<T> f(T); 

私は、彼らが真に機能的に同等ではありませんので、これは、おそらくが悪い形成されないと思います。 id_tという特殊化があるため、これら2つの宣言は実際には異なります。したがって、これらは実際は異なる宣言です。

+0

"id_t"がtypdef(iostreamを含める必要がある)のためにHaha、clang、およびgccがクラッシュする – AndyG

+0

実際には異なる宣言をすることが可能であることについて最後に良い点があります。このシナリオでは、結果の関数呼び出しの試行があいまいではないような特殊化を構成することも可能ですか? – AndyG

+0

@AndyGこれは、これは、あなたの答えの最後のコメントに投稿した質問です。 'id 'は特殊化できるので、 'T'と' id 'は同等ではありません。彼は本当に強いです! – Oliv

2

私は、このシナリオでは、彼らが異なると考えられていることを考える:

template<class T> 
struct t_{ 
    using type = T; 
    }; 
//ill-formed or different? 
template<class T> T f(T); 
template<class T> typename t_<T>::type f(T); 

[temp.over.link]と言うので(強調鉱山

2かどうかを決定するために の従属名は同等で、の名前のみが考慮され、の名前検索の結果は考慮されませんテンプレートのコンテキスト。

Ttypename t_<T>::typeは名前が異なるため、コンパイラはこれらのテンプレート宣言を受け入れます。今

、あなたはありません実際にコールそれらのどちらかでしたテンプレートのインスタンス化は曖昧で、その結果、機能的に同等あるため。この種のプログラムは不正であり、診断は必要ありません*(@Barry's great answer参照)。

MSVC 19.00.23506,clang 6.0.0およびはすべて私に同意しているようです(いずれも診断を発行しません)。

このようなものは、テンプレートがインスタンス化されていない場合でも、コンパイルされません一方、コンパイラは、そう長く彼らが呼ばれていないとして、これらのテンプレートを宣言することを可能にすることに注意してください:

template<class U> typename t_<U>::type f(U){return {};} 
template<class T> typename t_<T>::type f(T){return {};} 

* "機能が同等であるが同等ではないテンプレート テンプレートの宣言がプログラムに含まれている場合、プログラムは不正であり、診断は不要です "

+0

私は(このため[トリッキーな場合]のこの質問をhttps://stackoverflow.com/questions/47668769/when-defining-a-prototype-of-an-overloaded-c-function-template-is-it -legal-to?noredirect = 1#comment82308210_47668769)。私はコンパイラがすべて同意しているのを見たことがありますが、 "診断不要"のために、私は疑問を抱いていました。しかし、私はまだ疑問を呈しています。あなたが引用したパラグラフは同値*ですが、これは* functionalyと同等ではないことを排除しません。 – Oliv

+0

@オリーブ:私の理解が間違いない場合は、「同等」と「機能的に同等」を区別する必要があります。機能的に同等であることは可能ですが、それと同等ではなく、不公平です。 – AndyG

+0

「悪い」ではないことを証明するには、これらの宣言は「同等ではない」(あなたが行ったこと)であることを宣言しなければなりません。あなたは最後のデモンストレーションを行っていませんが、これはあなたの目に見えるかもしれませんが、これはまさに私の問題です。なぜ 't_ :: type'と' T'はfunctionnalyと等価ではないのですか? – Oliv

関連する問題