9

編集:私はWindows用のtdm-gcc-4.7.1-2を使用しています

これを解決する方法がわかりません。Bこれを一種の型リストとして使用して、のtypedefに存在しない型を使用しようとしていることを知らせたいと思います。

template <typename T, typename U>
struct A {
    typedef pair<T, U> type;
};

struct B : A<int, string>, A<int, float> {};

B::type foo; // won't compile, ambiguous reference, as expected
B::A<int, int>::type bar; // compiles fine?? :(

それを失敗させる方法A<int, int>(および他Aの'が継承されていないものB)、またはこれを回避する別の方法はありますか?を使用して、各要素とメタ関数にフィードするものを比較しtupleて、それを繰り返すことができると思いますが、これは簡単に思えました...最初は:\is_same

4

3 に答える 3

6

これは、クラステンプレートにtemplate-nameが挿入されているために発生します。挿入された名前は、テンプレートとして、またはテンプレートのインスタンス化(14.6.1p1)を参照するタイプとして使用できます。挿入されたクラス名は、派生クラス(10.2p5)に継承されます。テンプレートとして使用することは明確です(同じテンプレートですが、継承されます)ので、許可されます。

プログラムを修正するには、以下を使用してみてくださいis_base_of

struct B : A<int, string>, A<int, float> { };
template<typename T, typename U>
using check_A = typename std::enable_if<std::is_base_of<A<T, U>, B>::value, A<T, U>>::type;

check_A<int, float>::type bar1; // compiles
check_A<int, int>::type bar2; // error
于 2013-02-08T23:17:18.910 に答える
2

§11.1/5では、規格は次のように述べています。

派生クラスでは、基本クラス名を検索すると、宣言されたスコープ内の基本クラスの名前ではなく、注入されたクラス名が見つかります。注入されたクラス名は、それが宣言されたスコープ内の基本クラスの名前よりもアクセスしにくい場合があります。

Aのスコープに挿入された名前もそうですBA§14.1/4によると、基本クラスではなく(あいまいなため)テンプレートを参照します。

のスコープと同じように、Aと言えばA、それはクラス自体です(ただし、このコンテキストではテンプレートです)。この挿入された名前を使用しているため、名前B::Aはと同じ::Aです。この振る舞いを抑える方法はないと思います。

于 2013-02-08T23:06:34.253 に答える
2

少し紛らわしいですが、標準では明示的にこれを許可しています。ドラフトの14.6.1-4から:

インジェクトされたクラス名(10.2)を見つけるルックアップは、特定の場合(たとえば、複数の基本クラスで見つかった場合)にあいまいさをもたらす可能性があります。見つかったすべての注入されたクラス名が同じクラステンプレートの特殊化を参照し、名前の後にtemplate-argument-listが続く場合、参照はクラステンプレート自体を参照し、その特殊化は参照しません。あいまいではありません。

[ Example: 
template <class T> struct Base { }; 
template <class T> struct Derived: Base<int>, Base<char> { 
typename Derived::Base b; // error: ambiguous 
typename Derived::Base<double> d;// OK 
}; 
— end example ]
于 2013-02-08T23:07:02.060 に答える