Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: disambiguate this code at compile time?

i tried to find a way to disambiguate this code (at compile time) (since two days :-) -> get_value is ambugiuous.

#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;
}

This is a working runtime solution.

#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;
}

Is there a solution?

Note: a possible way that i found is over std::is_base_of<>, but this is very limited ( template instantiation depth )

like image 723
Monotomy Avatar asked Aug 11 '13 22:08

Monotomy


1 Answers

This is an ambiguous name lookup, which in the case of multiple inheritance hides the names in the look-up. It doesn't even get to checking which overload to use.

You can fix this by adding the following to struct A's definition:

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

These two statements add the name get_value from both base classes to A, and thus the compiler can then move on with its dreary life and check them as overloads.

like image 173
user Avatar answered Sep 21 '22 21:09

user