6

このコードを (コンパイル時に) 曖昧さをなくす方法を見つけようとしました (2 日後 :-) -> get_value があいまいです。

#include <iostream>

template <typename T>
struct type2type {};

template<class T, int val>
struct BASE
{
  static constexpr int get_value ( type2type< T > )
  {
    return val;
  }
};

class X {};
class Y {};

struct A :
  public BASE< X, 1 >,
  public BASE< Y, 0 >
{};

int main ( int argc, char **argv )
{
  A a {};
  std::cout << a.get_value ( type2type< X >{} ) << std::endl;
}

これは実用的なランタイム ソリューションです。

#include <iostream>

template <typename T>
struct type2type {};

template<class T>
struct VIRTUAL
{
  int get_value () const
  {
    return get_value_from_BASE ( type2type< T > {} );
  }
private:
  virtual int get_value_from_BASE ( type2type< T > ) const = 0;
};

template<class T, int val>
class BASE :
  public VIRTUAL< T >
{
  virtual int get_value_from_BASE ( type2type< T > ) const override
  {
    return val;
  }
};

class X {};
class Y {};

struct A :
  public BASE< X, 1 >,
  public BASE< Y, 0 >
{};

int main ( int argc, char **argv )
{
  A a {};
  std::cout << a.::VIRTUAL< X >::get_value () << std::endl;
}

解決策はありますか?

注:私が見つけた可能な方法はstd::is_base_of<>ですが、これは非常に限られています(テンプレートのインスタンス化の深さ)

4

2 に答える 2

7

これはあいまいな名前のルックアップであり、多重継承の場合、ルックアップで名前が隠されます。どのオーバーロードを使用するかをチェックすることさえできません。

struct Aの定義に次を追加することで、これを修正できます。

using BASE<X,1>::get_value;
using BASE<Y,0>::get_value;

これらの 2 つのステートメントは、両方の基底クラスの名前を A に追加するget_valueため、コンパイラは退屈な生活を続けてオーバーロードとしてチェックすることができます。

于 2013-08-11T22:49:18.337 に答える
2

Atash の回答に基づいて構築: ベースのリストと using 宣言でベース クラスのリストを再入力したくない場合は、次のような間接指定を使用できます。

#include <iostream>

template <typename T>
struct type2type {};

template<class T, int val>
struct BASE
{
  static constexpr int get_value ( type2type< T > const& )
  {
    return val;
  }
};

class X {};
class Y {};

template <typename...> struct AUX;

template <typename Base, typename... Bases>
struct AUX<Base, Bases...>: Base, AUX<Bases...> {
    using Base::get_value;
    using AUX<Bases...>::get_value;
};

template <typename Base>
struct AUX<Base>: Base {
    using Base::get_value;
};

struct A :
    public AUX<BASE< X, 1 >, BASE< Y, 0 > >
{
};

int main ()
{
  A a {};
  std::cout << a.get_value ( type2type< X >() ) << std::endl;
}
于 2013-08-11T23:01:00.153 に答える