C++ 从同一模板派生的模板类

C++ 从同一模板派生的模板类,c++,templates,c++14,C++,Templates,C++14,我有一个相当于以下代码的代码: struct Empty { static constexpr int id = 0; }; template <typename Self, typename Base = Empty> struct Compound : public Base { int get_id() const { return Self::id; } }; struct A : Compound<A> { static cons

我有一个相当于以下代码的代码:

struct Empty {
  static constexpr int id = 0;
};

template <typename Self, typename Base = Empty> struct Compound : public Base
{
  int get_id() const
  {
    return Self::id;
  }
};

struct A : Compound<A>
{
  static constexpr int id = 0xa;
};

struct B : Compound<B, A>
{
  static constexpr int id = 0xb;
};

template <typename T, typename Base> int get_id(const Compound<T, Base> &c)
{
  return c.get_id();
}


int test_a()
{
  A var;
  return get_id(var);
}

int test_b()
{
  B var;
  return get_id(var);
}
测试_b未编译,出现以下错误:

error: no matching function for call to 'get_id(B&)'
   return get_id(var);
                    ^
note: candidate: template<class T, class Base> int get_id(const Compound<T, Base>&)
 template <typename T, typename Base> int get_id(const Compound<T, Base> &c)
                                          ^
note:   template argument deduction/substitution failed:
note:   'const Compound<T, Base>' is an ambiguous base class of 'B'
   return get_id(var);
我明白这是为什么。B是派生的,可转换为化合物和化合物

我想知道是否有可能在C++14复合模板的上下文中进行更改,并获取_id函数,这样它将返回0xa表示A,0xb表示B,并可用于任意长的继承链


我知道用A和B中重写的虚函数可以很容易地解决这个问题,但如果可能的话,我希望避免这种情况。无论在何处使用这些类型,它们都是在编译时已知和固定的,因此不需要产生运行时开销。

您的帖子不清楚为什么需要在get_id中使用复合路径。您可以简单地使用:

template <typename T> int get_id(T const& c)
{
  return T::id;
}
简单一点:

template <class T>
auto get_id(T const& c) -> decltype(c.get_id())
{
    return c.get_id();
}

你不需要c是一个复合词,你只需要它有一个get_id成员函数

B可以转换为复合和复合-这就是模棱两可的基类的意思。你不能有模板结构复合:公共的。。。{/*...*/}; ?在A和B中都需要化合物中的功能。这里用简化的形式表示为get_it方法。最后做了一些非常类似的模板typename std::enable_if::type get_idconst T&c{return c.get_id;}