4

私はg ++ 4.4と4.5で奇妙な問題を発見しました。私はこれについて尋ねました。なぜなら、私はコード内にばかげたエラーを作り出していると思ったからです。オリジナルのポストはhereですが、ポストcompletitudeのために私はここで問題に問題のあるコードを再投稿されます:私はいくつかのあいまいなルールを欠けている可能性がありますalthought本当にプログラマのエラーではないようですテンプレートテンプレートパラメータは、以前のパラメータから解決されたパラメータを受け取ることができますか?

$ cat templatetemplate.cc 
template <int i> 
struct LabelTypeMap { typedef int type_t; }; 

template <bool> 
struct Hold { typedef int type; }; 

template<typename Holder, template<typename Holder::type> class typeMap> 
struct Whatever { }; 

template <bool Enable> 
struct Now { typedef Whatever<Hold<ENABLE>, LabelTypeMap> concrete_t; }; 

Now<true>::concrete_t obj; 

$ g++ -DENABLE=Enable -c templatetemplate.cc 
templatetemplate.cc:11: error: type/value mismatch at argument 2 in template parameter list for ‘template<class Holder, template<typename Holder::type <anonymous> > class typeMap> struct Whatever’ 
templatetemplate.cc:11: error: expected a template of type ↵ 
    ‘template<typename Holder::type <anonymous> > class typeMap’, got ↵ 
    ‘template<int i> struct LabelTypeMap’ 
[email protected]:~/play$ 
$ g++ -DENABLE=true -c templatetemplate.cc 
(no error) 

テンプレートテンプレートパラメータ解像度のしかし、私はバグをubuntuトラッカーに投稿しようとしました(うまくいけば彼らはそれを却下するか、そうでなければバグをアップストリームに送るでしょう)

これは本当にバグかどうかを調べるために、標準と私は今14.3.3セクションを2回読んだことがありますが、サンプルコードのようにパラメータを持つテンプレートテンプレートパラメータを渡すことが許されているのか許されていないのか分かりません。私はこの文書のこの部分がこれについて何も言及していないと確信していません

ここに私の質問があります。

EDIT:この質問が1週間以上未回答になっているのはかなり面白いです。私は、ISO C++標準では、前のテンプレートパラメータを使用して後続のテンプレートパラメータのタイプを指定できるかどうかはわかりません少なくとも記載された形式で)、基本的には実施者が決定するために残されています。

第2 EDIT(2011/01/01):皆さん、私たちはすべて欠けているかもしれませんコンパイラ設計者が間違っている): 私はintel C++コンパイラXE 12.0でこれを試しましたが、私はこれを得ました:

$icpc ttemplatetemplate.cc -o ./x2test 
templatetemplate.cc(12): error: class template "LabelTypeMap" is not compatible with template template parameter "typeMap" 
    struct Now { typedef Whatever<Hold<Enable>, LabelTypeMap> concrete_t; }; 
              ^


compilation aborted for templatetemplate.cc (code 2) 
$ icpc --version 
icpc (ICC) 12.0.0 20101116 
Copyright (C) 1985-2010 Intel Corporation. All rights reserved. 
+0

海賊版C++標準へのリンクを削除しました。 ISOがあなたに海賊のコピーにリンクしていることが判明した場合、私は彼らがあなたと何をするのか分かりません。「ISO IEC 14882 2003 C++」について、ISOカタログで見つけて... :) –

+0

BTW、Clangはこのコードをうまくコンパイルします。そして、私はこれが無効であるという仕様を見ていない(私はそれが無効でなければならない理由は見当たらないが、その後はC++コンパイラの作成を試みたことがない)。だから私はこれが有効であると思っています。 –

+1

信じられないほど、私はiso C++標準を「海賊行為」する可能性があるとは知らなかった。一般に公開されていない標準のポイントは何ですか? おとぎ話! - はい、私はclangを試してみましたが、それも私のために働くので、これは単なるg ++のバグです – lurscher

答えて

1

私はこの単純なコードを試みたが、私は、それを禁じ標準で何かを見つけることができませんComeauで(私には思えるあなたの問題を簡略化したものである):

template<int> 
class A {}; 

template<class T, template<T> class U> 
class B {}; 

B<int, A> b; 

そして、それは次のエラーを生成します。

"ComeauTest.c", line 4: error: a parameter of a template template parameter cannot depend on the type of another template parameter

私は実際にそれを禁じている標準の一部で見つけることがしたい...

+0

テンプレートテンプレート引数の構文'、テンプレートクラスU>。あなたが得るエラーは、大まかには「テンプレートA は、テンプレートテンプレートパラメータU の有効な引数ではありません。だから、Uがテンプレートテンプレートのパラメータでない場合、それは何ですか? – MSalters

+0

@MSalters:申し訳ありませんあなたのコメントを理解できません:(私は 'U'はテンプレートテンプレートパラメータですが、私がOP問題から理解しているのは、彼が*非タイプ*テンプレートパラメータを持つことが他のテンプレートパラメータ(' T')これは私の単純な例で再現しようとしたものです。 – icecrime

+0

あなたのアプローチはこのようには機能しません。 'A 'はタイプで、テンプレートタイプの引数にすることができます。テンプレートテンプレートの引数にすることができますあなたはミックスを目指しています。あなたが望むと思われるのは 'int、A'を渡して' A 'を得ることです。 T、テンプレート class UTempl>クラスB {typedef UTempl U; }; ' – MSalters

-1

は、可能になっているか、このはありませんか?

これは、LabelTypeMap自体がテンプレート(テンプレートテンプレートパラメータ)であり、したがって型を指定する必要があるためです。

template <bool Enable> 
struct Now { typedef Whatever<Hold<ENABLE>, LabelTypeMap<ENABLE> > concrete_t; }; 
+0

いいえ、typeMapがテンプレートテンプレートパラメータであるため、具体的なタイプ(LabelTypeMap )ではなくテンプレート(LabelTypeMap)が必要です。これはあなたが意味することですか?インスタンシエーションホルダーの – lurscher

0

私はこの奇妙な構造を疑っています:はずがすることは何template<typename Holder::type> class typeMaptypename Holder::typeビットは変です。それはダミーの名前(識別子)であるはずです。 Holder::typeは識別子でもありません。

+0

は、今すぐクラスするパラメーターに応じて、保留または保留になります。ホールド ::タイプとホールド ::タイプは両方ともintのtypedefです。テンプレートテンプレートパラメータの宣言では、typeMapはパラメータとして整数定数をとるテンプレートです。 – lurscher

+0

ああ、そうです、それが問題です。あなたは偽の 'typename'を持っています。 'typeMap'が型を取るテンプレートでなければならないときは' template class typeMap'を使います。 'typeMap'が整数をとるテンプレート(' LabelTypeMap 'のようなもの)の場合は' template class typeMap'を使います。後者の場合は 'typename'がないことに注意してください。 – MSalters

+0

だから、基本的には、 'Holder :: type'は従属名と型ですが、' typename'を使用することはできません。これは型を取るテンプレートテンプレートのパラメータに使われるためです。要約すると(!):前のテンプレートタイプ引数(phew)に依存して、型引数が従属名であるテンプレートテンプレート引数を渡したいとします。 – MSalters

1

ところで、ここで私は、根本的な問題に見つかったソリューションです:

template <int i> 
struct LabelTypeMap { typedef int type_t; }; 

template <bool> 
struct Hold { typedef int type; }; 

template<typename Holder> 
struct Whatever { 
    typedef typename Holder::type HT; 
    template <template <HT> class typeMap> 
    struct Whatever2 { }; 
}; 

template <bool Enable> 
struct Now { typedef typename Whatever<Hold<Enable> >::Whatever2<LabelTypeMap> concrete_t; }; 

ネストされたテンプレートを使用するが、私はtypedef経由typenameを導入することができます。

+2

'typename Holder :: type'はテンプレートパラメータとして使用できないという印象を受けているようです。しかし、Standardは特にこれを曖昧にしています。修飾名が 'typename'の後に使用されるならば、使用は非型テンプレートパラメータを導入します。修飾されていない名前が 'typename'の後に来ると、型テンプレートパラメータが導入されます。 –

関連する問題