模板类内部类作为函数参数时出现问题

5
我在类模板中使用内部类时遇到了问题。我有一个模板类(比如:Matrix<T>),和一个子类(比如:Matrix<T>::Row)。现在我想写一个函数来操作子类的实例(比如:negate(Matrix<T>::Row &)),我尝试用template<class T> negate(typename Matrix<T>::Row &)来声明该函数,但当我尝试使用它时,编译器告诉我找不到匹配项。
以下是一个抽象的示例:
template<class T>
class A
{
public:
    class B
    {
    };
};

template<class T>
void x(typename A<T>::B &)
{
}

int main()
{
    A<int>::B b;
    x(b); // doesn't work: Error: Could not find a match
          // for x<T>(A<int>::B) needed in main().
    x<int>(b); // works fine
}

为什么编译器在第一个情况中找不到 x? 有没有一种方法可以修改以使其工作(而不必显式指定类型 int)?
(我也遇到了类似的问题,其中 x 的形式为 template<class T,class S> void x(typename A<T> ::B&,const S&);,因此我真的不想在调用时强制命名所有类型。)
我已经尝试过 g++ 4.4.3、g++ 4.5.2 和 Sun Studio 5.9,它们都给出了相同的结果。非常感谢您提供任何有帮助的信息!

+1 鼓励使用 SSCCE - Flexo
3个回答

3
编译器应该如何推断这个呢?想象一下以下的设置:
struct A { typedef int T; };
struct B { typedef int T; };

template <typename S> void foo(typename S::T);

现在当你说int x; foo(x);时,没有办法进行明确的匹配。
重点是,您不是从给定的类模板中推导模板参数,而只是一个任意的、独立的类型。这个类型被定义在另一个类中并不相关。

有道理,谢谢!我想我会将我的类Matrix<T>::Row更改为MatrixRow<T>,这可能是解决我的问题的最佳方案。 - felix

2

这是不可推导的上下文。这就是为什么编译器无法推导模板参数。

想象一下,您可能已经将 A 特化如下:

template <>
struct A<SomeType>
{
    typedef std::map <double, double> B;
};

现在,这个专业有一个名为B的嵌套类型,它是std::map<double,double>的别名。

那么,如果A<SomeType>::B等于std::map<double,double>,编译器如何推导出类型SomeType

实际上,可能会有很多这样的特化,例如:

template <>
struct A<SomeOtherType>
{
    typedef std::map <double, double> B;
};

即使这个专业化有B作为嵌套类型。

现在,如果我说A<T>::Bstd::map<double,double>,那么你能说出T是什么吗?它是SomeType还是SomeOtherType


谢谢你的回答!我本来以为,由于我的代码只有一种解析方式,编译器会自动处理。但是我错了... - felix

1

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