部分的な順序と機能テンプレートをundeducedコ
-
19-09-2019 - |
質問
読み込み中に別の質問にあったが、問題の部分的な順序付けは、切り以下のテストケース
template<typename T>
struct Const { typedef void type; };
template<typename T>
void f(T, typename Const<T>::type*) { cout << "Const"; } // T1
template<typename T>
void f(T, void*) { cout << "void*"; } // T2
int main() {
// GCC chokes on f(0, 0) (not being able to match against T1)
void *p = 0;
f(0, p);
}
両方の機能をテンプレートのタイプの専攻に入る負荷分解能 void(int, void*)
.だが部分的な順序付け(comeau、GCC)現在のような第二のテンプレートがあります。でも、なぜでしょう?
についてお話しして部分的な順序を示しています。月 Q
する独自の作られた、型を決定するために用いる部分的な順序付けによる 14.5.5.2
.
- 変形パラメータ-リスト
T1
(Q挿):(Q, typename Const<Q>::type*)
.の種類の引数AT
=(Q, void*)
- 変形パラメータ-リスト
T2
(Q挿):BT
=(Q, void*)
, あるもの種類の引数になります。 - 非変形のパラメータ-リスト
T1
:(T, typename Const<T>::type*)
- 非変形のパラメータ-リスト
T2
:(T, void*)
以来、C++03下を指定しこ、なんとなく使っていたの意図について複数の欠陥ます。上記の変形パラメータのリスト T1
と呼ばれる AT
私として使用してい引数リスト 14.8.2.1
"Deducingテンプレートの引数から関数呼び出".
14.8.2.1
なに変換 AT
または BT
ももなどの除去、参考declaratorsなど)を、ひたすら直進し金属を磨くとる 14.8.2.4
, 自社の各 A
/ P
ペアになタイプの控除:
AT
対T2
:{
(Q, T)
,
(void*, void*)
}
.T
のテンプレートパラメータをここで見るT
必要Q
.タイプ控除に成功しtrivially用AT
対T2
.BT
対T1
:{
(Q, T)
,
(void*, typename Const<T>::type*)
}
.このディレクティブT
はQ
, もこちらです。typename Const<T>::type*
は国連が予測コンテキストではな使用が推ものです。
ここでは私の最初の質問:この利用価値の T
を導出のための最初のパラメータ?答えがnoの場合は、最初のテンプレートがあります。このできないので、GCCおよびComeauという第二のテンプレートより専門的な、とは思っていないその考えは間違っている。いえ"はい"の挿入 void*
入 T
.の条(14.8.2.4
いてるという。 "控除を行う独立のためにペアごとの結果を合わせた" とも "特定のコンテキストは、価値のない参加型の控除であり、グリーンハウスよりの価値のテンプレートの引数には、推定外または明示的に指定します。" この音のように"yes"です。
控除そのため成功においても、毎A/Pのペアにします。現在、各テンプレートものとして専門として、が控除さんも、暗黙的な変換に成功したのです。その結果、話すべき曖昧なものです。
その後、私の第二の質問:今、なぜ、実装という第二のテンプレートの専門?何をしたものまでが一望できま?
編集:いたしまし明示的な専門性とインスタンス生成は、近GCCバージョン(4.4
いることを参考に専門性が曖昧ながらの古いバージョンのGCC4.1
な上昇により義エラーとなります。こうした最近のGCCのバージョンでは、矛盾した部分的な順序付けのための機能テンプレート。
template<typename T>
struct Const { typedef void type; };
template<typename T>
void f(T, typename Const<T>::type*) { cout << "Const"; } // T1
template<typename T>
void f(T, void*) { cout << "void*"; } // T2
template<> void f(int, void*) { }
// main.cpp:11: error: ambiguous template specialization
// 'f<>' for 'void f(int, void*)'
解決
ここでの私です。い チャールズベイリー ることがないよう、正しい情報はなっていくことになるでしょう Const<Q>::Type*
へ void*
template<typename T>
void f(T, typename Const<T>::type*) { cout << "Const"; } // T1
template<typename T>
void f(T, void*) { cout << "void*"; } // T2
において
14.5.5.2/2
二つの過負荷機能テンプレート、より専門的なこのように求めることができ換各テンプレートに用引数を控除14.8.2)が新たに発足することになったのです。
14.5.5.2/3-b1
タイプ毎のテンプレートパラメータの合成に独自のタイプおよび代替するための各発生するパラメータの関数パラメータのリストは、テンプレート変換機能に戻ります。
私の考えでは、この種類は以下のようにして合成:
(Q, Const<Q>::Type*) // Q1
(Q, void*) // Q2
と思いますかる表現とその合成パラメータの T1
すると void*
.わからないのは先例が、ほかのコンテキストです。タイプ Const<Q>::Type*
完全に有効なタイプのC++タイプシステム。
そこで、私たちは今、行額控除の手順:
第2四半期において対前期比でT1
したが推テンプレートのパラメータT1しておりますので:
- パラメータの1:
T
を導き出するQ
- パラメーター2:Nondeducedコ
でもパラメータ2は不明で、控除が成功しい価値T.
第1四半期にT2
DeducingテンプレートのパラメータT2い:
- パラメータの1:
T
を導き出するQ
- パラメーター2:
void*
一致しないConst<Q>::Type*
な控除に失敗。
まぁ、こちらの基準を可能にしてくれます。パラメータには含まれておりませんのでめったに明らかにすべきである、しかし、私の経験に基づくsquinted読みの14.8.2.1/3)である場合でもパラメータPタイプには含まれておりません、その引数の型と一致します。
に合成された引数のT1に使用できる専門T2場合も同様であった。T2がますます増加するという専門的なもののT1での機能です。
更新1:
でをカバーしpoing約 Const<Q>::type
ています。次の例を考えてみてください:
template<typename T>
struct Const;
template<typename T>
void f(T, typename Const<T>::type*) // T1
{ typedef typename T::TYPE1 TYPE; }
template<typename T>
void f(T, void*) // T2
{ typedef typename T::TYPE2 TYPE ; }
template<>
struct Const <int>
{
typedef void type;
};
template<>
struct Const <long>
{
typedef long type;
};
void bar ()
{
void * p = 0;
f (0, p);
}
その上、 Const<int>::type
る場合に使用い、通常の過負荷分解能のルールがない場合または一部をオーバーロード。い選択任意の専門性のための Const<Q>::type
.できない場合があり直感的に、コンパイラは非常に喜んでいsynthasizedタイプの形 Const<Q>::type*
活用することに型式控除の対象
更新2
template <typename T, int I>
class Const
{
public:
typedef typename Const<T, I-1>::type type;
};
template <typename T>
class Const <T, 0>
{
public:
typedef void type;
};
template<typename T, int I>
void f(T (&)[I], typename Const<T, I>::type*) // T1
{ typedef typename T::TYPE1 TYPE; }
template<typename T, int I>
void f(T (&)[I], void*) // T2
{ typedef typename T::TYPE2 TYPE ; }
void bar ()
{
int array[10];
void * p = 0;
f (array, p);
}
場合に Const
テンプレートのインスタンスを生成と価値 I
, で再帰的にinstantiatesそのものまで I
が0になります。この場合、一部の専門 Const<T,0>
を選択します。また、コンパイラに合成する実際の型パラメータの機能、そしてどのような価値を持ち得るのにコンパイラを選択、配列インデックス?10?もなり得るかということですが、細かの例がるのではなく、試合は一部の専門 Const<T, 10 + 1>
る概念的には少なくとも、結果無数の再帰的instantiationsになります。うる値で選択した変更の状態にその値に+1することも無限ループの部分的な順序付けアルゴリズムです。
うまくいかないときはどのように部分的な順序付けアルゴリズムが正しくインスタンスを生成 Const
何かという type
プラットフォームに対応
他のヒント
編集:を学んだ後、 Clangの 実施(Doug Gregor)の部分的な順序付けアルゴリズムを、私なりに同意のポスターの独自の例あるいは目的に、"曖昧なものを標準は明確でない.このような状況.私は編集後記私の改正の思い(自分の利益およびリファレンス"を参照).特にClangのアルゴリズムを明らかにする'typename Const<T>::type
ができるようになりに翻訳'無効の部分発注段階、それぞれA/Pのペアを導き出すと独立します。
当初はなぜ、以下の考えられた曖昧なもの:
template<class T> void f(T,T*); // 1
template<class T> void f(T, int*); // 2
f(0, (int*)0); // ambiguous
(The above is ambiguous because one cannot deduce f1(U1,U1*) from f2(T,int*), and going the other way, one cannot deduce f2(U2,int*) from f1(T,T*). Neither is more specialized.)
が以下のような曖昧なもの:
template<class T> struct X { typedef int type; };
template<class T> void f(T, typename X<T>::type*); // 3
template<class T> void f(T, int*); // 2
その理由と見込まれる曖昧なものは以下の場合に起こる:
- f3(U1,X<U1>::type*) -> f3(U1, int*) ==> f2(T,int*) (deduction ok, T=U1)
- f2(U2,int*) ==> f3(T, X<T>::type*) (deduction ok, T=U2 makes X<U2>::type* -> int*)
であればtrue、いつもより専門的なものにします。)
を学んだ後、Clangの部分的な順序付けアルゴリズムは明らかであっ'3'上しました:
template<class T, class S> void f(T, S*); // 4
でを控除したユニークな日付/時刻パターン文字"U"に対'typename X::タイプ'成功-
f3(U1,X<U1>::type*) is treated as f3(U1, U2*) ==> f2(T,int*) (deduction not ok)
f2(U2,int*) ==> f3(T,S* [[X<T>::type*]]) (deduction ok, T=U2, S=int)
その場合は2はかなり専門的なものに'3'.
T1(Qための形質転換したパラメータリスト 挿入された):(Q、型名 Const ::タイプ*)。の種類 引数は=(Q、void *型)
にあり
それが本当に正しい単純化である場合、私は疑問に思います。あなたがタイプQ
を合成するときは、テンプレートspecliazationの順序を決定する目的のためにConst
のために専門を想起することが許可されている?
template <>
struct Const<Q> { typedef int type; }
T2
パラメータは任意のテンプレートパラメータのためT1
の二番目のパラメータと一致しないため、このは少なくともvoid*
として専門されていないように、そのT1
を暗示ます。
編集:を無視してくださいこのポストを学んだ後、clangsアルゴリズムの一部を発注して実施するDoug Gregor(だけであっても一部実施しているこの書面はなく、この論理の関係のOPの問題は十分に足りなが表示されているundeducedとしてコンテキストで別のテンプレートパラメータとします。この過負荷の明示的なvoid*引数の特殊なバージョンがないように定義しています。通常通りComeauに通知するものとします。現在の文言の基準を明確に定義この挙動-その他物...
このポストにも掲載してcomp.lang.c++.モデレート、そう戸惑いがありすぎながらよく集めたものだと思うの後の私の答えするグループはここでも-ての議論を明らかに関連のある問題です。
On Jul 25, 1:11 pm, Bart van Ingen Schenau <b...@ingen.ddns.info> wrote:
You are going one step too fast here. How do you know (and would the compiler know) that there is no specialisation of Const<Q> such that Const<Q>::type != void?
As far as I can see, the compiler would transform the parameter-list of A to: AT=(Q, <unknown>*). To call B with these parameters requires an implicit conversion (<unknown>* to void*) and therefore A is less specialised than B.
と思いこが間違っています。が確認されている機能です。
専門(部分順序)、コンパイラを変換します
パラメータのリストへ (Q, void*)
-するそして実際にinstantiatesの関係
テンプレート(ベストマッチング)を見て内での価値'タイプ'-この場合、
のテンプレートで無効*.
についての点に関する一部の専門性が確認 るテンプレートは専門のその他のタイプに使用できる は、ユニークな発生するタイプがある場合にはその他の専門分野の のインスタンス生成の宣言時に過負荷の決議がなされている) 彼らが考えられます。を追加する場合はその場では、得しなければならない選択 する違反のODR(14.7.4.1)
の一部/明示的な専門性もconsidertaion中 形成のセットがこの種の実際の引数 の機能です。場合にベストマッチング部分の専門性(X)の結果 機能タイプがより良い暗黙的に変換配列の一部 パラメータ、そのことは一切ございませんので、一部の秩序相が "よりよい"機能を取得しま選択されたものの一部 秩序相)
ここでは例と言うべきもの各種手順:
template<class T, bool=true> struct X; // Primary
template<class T> struct X<T,true> { typedef T type; }; // A
template<> struct X<int*,true> { typedef void* type; }; // B
template<class T> void f(T,typename X<T>::type); //1
template<class T> void f(T*,void*); //2
int main()
{
void* pv;
int* pi;
f(pi,pi);
// two candidate functions: f1<int*>(int*,void*), f2<int>(int*,void*)
// Note: specialization 'B' used to arrive at void* in f1
// neither has a better ICS than the other, so lets partially order
// transformed f1 is f1<U1>(U1,X<U1,true>::type) --> f1<U1>(U1,U1)
// (template 'A' used to get the second U1)
// obviously deduction will fail (U1,U1) -> (T*,void*)
// and also fails the other way (U2*, void*) -> (T,X<T>::type)
// can not partially order them - so ambiguity
f(pv,pv);
// two candidate functions: f1<void*>(void*,void*), f2<void>(void*,void*)
// Note: specialization 'A' used to arrive at second void* in f1
// neither has a better ICS than the other, so lets partially order
// transformed f1 is f1<U1>(U1,X<U1>::type) --> f1<U1>(U1,U1)
// (template 'A' used to get the second U1)
// obviously deduction will fail (U1,U1) -> (T*,void*)
// and also fails the other way (U2*, void*) -> (T,X<T>::type)
// can not partially order them - so ambiguity again
}
でも触れた場合には、主なテンプレートには定義しSFINAE作業中に作動し、部分的な順序相 もので明らかにされたのか、曖昧であるべきます。
ものを追加した場合、別のテンプレートに繋がるもの試合の場合はポイントinstantationのいずれかの機能で別の場所へ移動翻訳単位で明らかに違反するODR.
On Jul 25, 1:11 pm, Bart van Ingen Schenau <b...@ingen.ddns.info> wrote:
第一に、より専門的な料理:パルタマではあら 少ない 種 そのテンプレートを選択できる負荷。これを用いて、規則の一部をご注文可能の検討として、してみて を見つめるようなきが億いない、または過負荷 解像度の好みと呼A.そのタイプに見ることができBがあり 専門よA.
引数を指定しない。でのルールに基づいて現在、OPの例は 曖昧なものです。
最後に、明示的な、明白な答えは特定の質問はlitb:
1)この利用価値の導出のための最初のパラメータ?
ありのコースでは、行ってテンプレートの引数を控除-
にリンクしていを維持できます。
2)それで、なぜ、実装というのは、より専門的なょうか?
間違っているため;)
この問題に休養-くださいがあるのであれば、そのことは未だよくわかっていません:)
編集:litb上げたんにコメント、何かにこのテンプレートは常に取得し
のインスタンス生成の発生タイプが強すぎています。
ものがある主なテンプレート呼び出されません。
うどんどんでは部分的な順序付けは庭を、独自の生成タイプ
使用に合わせて最高の専門性を高めます。そうかもしれませんので、する必要はありませんのテンプレートを作成します。いのブラウザに送信され、上記の言語です。また、に関する問題を定義するより良いマッチングテンプレート後のポイントinstantation.する違反のODRによる節点のインスタンス生成.
標準という一度A/Pのペアの作成を使用してルールの変革に記載のとおり温度func.注)その推定の用テンプレートの引数を控除(温度控除)する部門の担当の場合は不明でのコンテキストスをインスタンス化のテンプレート及びその入れ子型発動ポイントのinstantiations.の温度点部のODR違反の意味の部分的な順序付けは変わらないに関わらずポイントのinstantation内訳単位)。いが、混乱する。–ファイサルVali1時間前から[削除するコメント]
litb:"このステップとQにConst::タイプの構築の議論に覆われていないによって明示的にはSFINAEます。のSFINAEルール作の引数を控除し、の項をQの機能テンプレート機能パラメータのリストで14.5.5.2.'
のSFINAEルールを使用するこちらの方もいらっしゃるかもしれません。だと思いますが、十分に示唆-こんなに否定することが明をするにあたり、私は委員会が明らかに このせいではないと思いニーズを明らかにする解釈を与える。
私の供をリンクします。(14.8.2):が明示的にテンプレートの引数リストが指定されたテンプレートの引数に対応していることが必要となる テンプレートパラメータのリスト、結果の有効な機能タイプとして以下に記載するその他の型の控除 失敗した"
(14.5.5.2/3) "変換に使用す:—タイプ毎のテンプレートパラメータの合成に独自のタイプおよび代替するための各発生 このパラメータの関数パラメータのリストは、テンプレート変換機能に戻ります。"
私の心は、上記の見積もりとき"を"ならではの発生の種類毎のテンプレートパラメータの関数が宣言する implicityインスタンスを生成する 明示的に 供給の種類としてのテンプレートの引数に当社の機能テンプレートを作成します。この結果を無効となっ 機能タイプ、その後の変化よりも重要なのはその後のテンプレートの引数を控除に必要な 一部の機能が失敗します。
(14.5.5.2/4) "利用の変換機能パラメータのリストを行う引数を控除に対するその他の機能テンプレートを作成します。変換されたテンプレート ものとして専門としてのその他の る場合に限り、, の控除成功に導き出すパラメータ型 は完全一致の控除に頼らない暗黙的に変換)."
場合、変換機能パラメータのリストへの置換に失敗して知ら控除できないことに成功した。から控除しなかった、成功ではないとして専門としてのその他はすべてなのかを知っておく必要がありま進む 部分的な順序付けする。
litb:っていうこの場合:
template<typename T> struct A;
template<typename T> void f(T, typename A<T>::type); template<typename T> void f(T*, typename A<T>::type);
確実に ことになるindendedものを有効なコードがって::タイプで失敗しますので、 テンプレート定義のコンテキスト内で定義されていないか" もありませんの施設で定義されたテンプレートinstantiationsかになっ のような置換できるように決定出来ることを明らかにした順序付け(部分順序によって異ならない 他のコンテキストこの静的財産の機能をテンプレートは好評に終えることができました。.このような問題にする必要があるのを修正。
Ok-と思うんですがすものとは異なります。だから正しく、と思ってい これらの機能テンプレートの取得を宣言し、コンパイラでの部分的な順序付け、中でも に関わらず過負荷解決まっ動を選択します。いただく方法で解釈するので、そのまま出入り可能ですこの動きについて?解決方法/評価私としては、標準の求める又は義務付けます。
現在、標準の基準は、信用リスク分析と部分順序付けはagnosticのタイプで使用されるの呼び出し機能(いと思い これが、みなさんを参照している場合について説明していただけまでとしての静的財産である文脈を記入してください。
の基準も明らかで利益ばかり考えて行動してい部分順序(ソッドを呼び出し部分的な順序)の間での機能テンプレート 時の過負荷分解能(13.3.3/1)の場合だけことができていなかったり、より良い機能によりICまたは 場合には、テンプレートおよびその他のいません。[部分的な順序付けのクラステンプレート部分領域は別問題 私の心の関連コンテキスト(その他のテンプレート定義するとともに、インスタンス生成は特定のクラスです。]
このように、私の意見は機械の部分的な順序付けの機能テンプレート呼び出し時の過負荷 の決議が行われ、該当部分のコンテキスト(テンプレートの定義および専門性) 時の過負荷の決議を行っています。
なので私interepretationにしている例を'テンプレート構造体A'は、上記のコードが有効になります。の部分的な順序付けが行われませんの定義にコンテキストだがいを呼び出すと過負荷分解能 の機能による書面の呼び出しf(int*)0,0)と、その当時のコンパイラのいずれか という組み立て候補者宣言部または一部を注文して頂ければ、部分的な順序付けステップ) 場合には無効な表現や結果の一部として機能タイプ、SFINAEを行う るテンプレート控除に失敗したと部分順序付けに関することが できなり専門的なもののその他の場合とはできないものテンプレート).
現在については、連絡先のツださを確信するということで、変換機能をもっ は暗黙のinstantiationsを明示的に提供されたテンプレートの引数リストを使用して独自に発生するタイプ) これにより,以下のような標準的な引用符と関連する:
14.6.4.1/1の機能をテンプレートの専門性、機能テンプレートの専門性、専門性のための メンバー関数または静的データのクラステンプレートの場合、専門は暗黙のうちにインスタンスを生成 ですので参照される内から別のテンプレート専門のコンポーネントで参照される によってテンプレートパラメータ、ポイントのインスタンス生成の専門は、インスタンス生成 を囲む専門性を高めます。
の私の解釈では、この施設は、変換された機能タイプのorigianl機能タイプの 同施設のためにこれらの機能を実際に機能する。
litb:以来、部分的な順序付けがなけ
a property of the syntactic form of parameters (i.e "T*" against "T(*)[N]"),
私は投票を改正する仕様"のような場合はQが入れ子の名前の指定子 修飾-id名前タイプの型名が"Q"のマーク) またはこのタイプの名前は別のユニークなタイプです。This means that in template<typename T> void f(T, typename Const<T>::type*);
the argument list is (Q, R*), for example.
Same for template<typename T> void f(T*, typename ConstI<sizeof(T)>::type);
the arg lisst would be (Q*, R). A similar rule would be needed for non-type parameters, of course.
私は考えてプレーすることで、テストケースがこの利回りの自然の秩序あります。
Aah-現することが示唆される解決策を解決する曖昧さで決ま すべて直感的に期待-このは別問題ないの方向に向かうが、 となっており、私もいつかえでの前に宣言し、その加工性を有します。
り続ける。いいんじゃなく限界だけます。
にすることができるので編んだ対応の場合、投稿ることが容易といった利点があります。