2009-08-12 4 views
3

テンプレートを頻繁に使用するコードがあります。それはGCC上ではうまくコンパイルされますが、構文解析中に失敗するVS(2003年 - 2010年のベータ1でテスト済み)ではコンパイルされません。残念ながら、問題を減らして数行で再現できるコード構造は十分にわかりませんので、私は原因を推測することしかできません。私はここの誰かが正しい方向に私を向けることを望んでいます。私たちは、VS、(多くの中で)最初のエラーメッセージでコンパイルするとテンプレートのメンバtypedefが、VSでは宣言されていない識別子で、GCCでは宣言されていません。

template< class UInt, typename IntT, 
    bool is_signed = std::numeric_limits<IntT>::is_signed > 
struct uii_ops_impl; 

// .... 

template<class UInt> 
struct uii_ops_impl< UInt, 
    typename make_signed<typename UInt::digit_type>::type, true > 
{ 
    typedef UInt unbounded_int_type; 
    typedef typename make_signed< typename unbounded_int_type::digit_type >::type 
     integral_type; 

    // ... 

    static void add(unbounded_int_type& lhs, integral_type rhs); 

    // ... 
}; 

template<class UInt> 
void uii_ops_impl< 
    UInt, typename make_signed<typename UInt::digit_type>::type, 
    true >::add(unbounded_int_type& lhs, integral_type rhs) 
{ 
    // .... 
} 

それは返してい

です:エラーC2065: 'unbounded_int_type':宣言されていない識別子

私は、typedefでポイントを指しています huh? :-S

EDIT:

テンプレートパラメータとして使用されて

typename make_signed<typename UInt::digit_type>::type 

に何かがあると思われます。残りのコードでは、メンバ関数のパラメータで使用される同様のtypedefがうまくコンパイルされます。これまでのところ私が見ることのできる唯一の違いは、他のケースのどれもテンプレートパラメータとして上記の行がないことです。 make_signedはBoost.TypeTraitsのものです。

EDIT:まったく同じことが、それは罰金コンパイル、別のファイルで行われているため

さて、多分それは、それではないです。うーん...

バウンティEDIT:

さて、私はそれは、コンパイラが文句を言っている場合、問題は実際にはない、この時点では明らかだと思います。特定のポイントでの2つのメンバ関数定義のみが失敗します。明示的にパラメータを修飾すると、はまだにコンパイルされません。唯一の直接の解決策は、関数をインラインで定義することです。これは構文解析に合格します。ただし、std::allocator<void>size_typeのメンバーがないため、テンプレートをインストールしようとするとVSが失敗します。 VSは、size_typeを宣言していないT = voidの特殊化をstd::allocator<T>にしています。私はsize_typeがすべてのアロケータの必須メンバーだと思いましたか?

ここで問題になるのは、構文解析時にVSを非常に悪くして、完全に無関係な非問題をエラーとして訴え、そのようなコードをどのようにデバッグしますか?

p.s.余分な時間がある人のために、私がVSで仕事をしようとしているコードは、Kevin Soppのmp_mathがBoostのサンドボックスにあります。これはlibtommathに基づいています。

+0

これは最初のエラーですか?そうでない場合は、以前のエラーがコンパイラを混乱させる可能性が非常に高いです。 – sbi

+0

*「最初のエラーメッセージ(多くのうち)...」というメッセージにポイントする*: – KTC

+0

Visual C++で使用したテストケースコードを入れてもらえますか?多分元のコードとのいくつかの違いを理解することができます。 –

答えて

6

私は、これは

  • unbounded_int_typeは、その宣言はクラステンプレートに表示されます(14.6.2.1で定義)non-dependentタイプ
  • あるいくつかの状況によって発生することができると思います。依存しないため、メンバー関数が定義された時点でその名前を宣言に解決する必要があります。

Visual C++ではこのルックアップを実行できず、代わりにエラーが発生する可能性があります。誰かが言及したように、メンバ関数定義の型名を明示的に修飾することができます。型はそれに依存し、インスタンス化されるまで名前の参照を遅らせるコンパイラのメカニズムを起動します。

template<class UInt> 
void uii_ops_impl< 
    UInt, typename make_signed<typename UInt::digit_type>::type, 
    true >::add(typename 
       /* repeat-that-beast uii_ops...true> here */ 
        ::unbounded_int_type& lhs, 
       typename /* and here too */::integral_type rhs) 
{ 
    // .... 
} 
+0

'add()'の引数の型は、3.4.1(8) - 修飾されていない名前検索のルックアップ規則に従うべきです。適用するべきルールは、 "クラスXのメンバーであるか、またはXの基本クラスのメンバーでなければならない"ので、コンパイラーは名前を解決できるはずです。 KTCが示しているように、名前ルックアップは厳格な例で成功します。不特定のものが混在していて、問題が発生したときです。 –

+0

私は彼が小切手のためにどのような例を使用したか分かりませんでした。 'struct X {typedef int Ty;}のようなものです。 void f(Ty); }; void X :: f(Ty){} 'はうまくいっているかもしれませんが、もちろん別の状況です:) –

+0

あなたの答えにリンクする他のコードでは、私たちと同じ状況が起こります。彼らのために働く。おそらく、この場合、部分的な専門化が必要となるからです。 –

0

最初のエラーはどの行ですか?

この定義でunbounded_int_typeを使用してい:

template<class UInt> 
void uii_ops_impl< 
    UInt, typename make_signed<typename UInt::digit_type>::type, 
    true >::add(unbounded_int_type& lhs, integral_type rhs) 
{ 
    // .... 
} 

は完全に修飾する必要があります。

template<class UInt> 
void uii_ops_impl< 
    UInt, typename make_signed<typename UInt::digit_type>::type, 
    true >::add(uii_ops_impl<UInt, etc ,true>::unbounded_int_type& lhs, integral_type rhs) 
{ 
    // .... 
} 

+0

定義時にエラーが発生します。パラメータを明示的に修飾することでエラーを取り除くことは可能ですが、VSの例ではそれを必要としません。 – KTC

1

ここで面白いことだ -のtypedefは、問題を回避働いを使用して、その以外 - この男

はあなたが見ているものに非常に似ていますMSVCのバグに遭遇したが、彼のために。

私はまだ彼が遭遇した問題(またはあなたが走っている問題)をどうしたらいいのか分かりません。あなたが言うように、あなたが投稿した小さなスニペットはエラーを再現しません(make_signed<>::typeをコンパイル可能にする単純なmake_signed<>テンプレートを与えて)。

+0

私は実際に私が私の問題を抱えている可能性がある理由を探していたとき、以前にその質問を見ました。彼はArgument Dependent Lookupと何か関係があります。修飾された引数はADLをアクティブ化しませんが、修飾されていない引数はアクティブにしません。 – KTC

+0

他の質問のコードは、ADL(またはそれはしません)をしていない - 'SetToFirst()'関数が呼び出されていない、それが定義されています。とにかく、私はそれがあなたに何らかの形で(またはそれが実際に関連していても)助けになるとは確信していませんでしたが、...少なくとも面白いと私を襲った。 –

0

あなたはこの1にコンパイラを少し助けなければなりません。タイプを参照し、テンプレート・パラメーターに依存する修飾名があるので、typenameキーワードを使用する必要があります。

この点について考えてみると、どのようにunbounded_int_type::digit_typeがタイプであることを確認できますか?どのタイプがunbounded_int_typeであるかによって異なります。したがって、typenameキーワードを追加することであいまいさを取り除きます。

template< class UInt, typename IntT, 
bool is_signed = std::numeric_limits<IntT>::is_signed > 
struct uii_ops_impl; 

// .... 

template <class T> 
struct make_signed 
{ 
    typedef T type; 
}; 

template<class UInt> 
struct uii_ops_impl< UInt, 
    typename make_signed<typename UInt::digit_type>::type, true > 
{ 
    typedef UInt unbounded_int_type; 
    typedef typename make_signed< typename unbounded_int_type::digit_type >::type 
     integral_type; 

    // ... 

    static void add(unbounded_int_type& lhs, integral_type rhs); 

    // ... 
}; 

template<class UInt> 
void uii_ops_impl< 
UInt, typename make_signed<typename UInt::digit_type>::type, 
true >::add(unbounded_int_type& lhs, integral_type rhs) 
{ 
    // .... 
} 

唯一の変更はここにあります - typenameというキーワードを追加しました。

 
typedef 
typename make_signed< typename unbounded_int_type::digit_type >::type    integral_type; 
+0

あなたが投稿したものはまさに既にそこにあるものです.... – KTC

関連する問題