在模板类中嵌套模板类时的模板参数推导

4

我有一个模板类在另一个模板类内部。如何编写一个模板函数,可以接受内部/外部模板类的任意组合?

template <class X>
struct A
{
  template <class Y>
  struct B
  {
    int q;
  };
};

template <class X, class Y>
int f( typename A<X>::template B<Y>& ab )
{
  return ab.q;
}

int g( A<char>::B<short>& ab )
{
  return f( ab ); // Error: Could not deduce template argument
}
2个回答

2

此模板接受任何内部和外部的组合:

tempalte <typename T>
int f(T& ab)
{
    return ab.q;
}    

您无法从 typename A<X>::template B<Y> 推断出 XY。详情请参见此处:什么是非推断上下文?。根本问题在于名称 typename A<X>::template B<Y> 所引用的实际类型与 XY 之间不存在一对一关系。请考虑可能存在的特化情况:
template <>
struct A<double>
{
    template <class Y>
    using B = A<int>::B<Y>;
};

现在,A<double>::B<Y>A<int>::B<Y>指的是同一种类型。如果只给出其中一个,无法明确地推断出X


2

在这种情况下,编译器不允许推断模板参数,因此为了传递类型信息,必须显式指定。其中一种可能性是提供别名:

template <class X>
struct A
{
  template <class Y>
  struct B
  {
    using X_type = X;
    using Y_type = Y;
    int q;
  };
};

template <class T>
int f( T& ab )
{
  return ab.q;
}

int g( A<char>::B<short>& ab )
{
  return f( ab );
}

这样,您仍然可以访问类型,例如typename T::X_type


我的问题是,我已经有了一个适用于一般情况的 template <class T> int f( T& )。当 TA::B 时,我需要另一个 f() 的重载。我将尝试使用 std::enable_if 来解决这个问题... - Barnett
@Barnett 或许可以开一个更详细的问题来提供更多背景信息。 - 463035818_is_not_a_number
如果我已经有一个函数 template <class T> int f( T& t ) { return sizeof(t); },但现在我需要另一个重载的 f() 函数,它将返回 A<X>::B<Y>::q。@largest_prime_is_463035818 - Barnett
@Barnett 是的,我认为我理解了问题,并且我知道一个解决方案,尽管这不是这个问题所涉及的问题,而且评论也不是谈论冗长代码的地方(任何比你写的稍微长一点的东西在评论中都不可读/理解)。 - 463035818_is_not_a_number
@largest_prime_is_463035818,别担心,我已经按照@Jodocus的建议使用template <class T, class = typename T::X_type, class = typename T::Y_type> int f( T& )使其正常工作。 - Barnett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接