潜在的g ++模板错误?

Eva*_*ran 12 c++ templates g++

我遇到过一些我认为应该编译的代码,但是没有.所以我希望SO的一些当地标准专家可以提供帮助:-).

我基本上有一些类似于这样的代码:

#include <iostream>

template <class T = int>
class A {
public:
    class U {
    };

public:
    U f() const { return U(); }
};

// test either the work around or the code I want...
#ifndef USE_FIX
template <class T>
bool operator==(const typename A<T>::U &x, int y) {
    return true;
}
#else
typedef A<int> AI;
bool operator==(const AI::U &x, int y) {
    return true;
}
#endif

int main() {
    A<int> a;
    std::cout << (a.f() == 1) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

所以,来描述这里发生了什么.我有一个类template(A),它有一个内部类(U)和至少一个可以返回该内部类(f())实例的成员函数.

然后我试图创建一个operator==函数,将这个内部类型与其他类型进行比较(在这种情况下是一个int,但似乎并不重要).

如果USE_FIX没有定义的,我得到以下错误:

test.cc: In function 'int main()':
test.cc:27:25: error: no match for 'operator==' in 'a.A<T>::f [with T = int]() == 1'
Run Code Online (Sandbox Code Playgroud)

这看起来很奇怪,因为我很清楚(我认为)定义了一个operator==应该覆盖它的模板,实际上如果我只是为编译器做一些工作(启用USE_FIX),那么我就不会再出错了.不幸的是,"修复"一般不起作用,仅用于模板的特定实例化.

这应该按照我的预期工作吗?或者这是不允许的?

顺便说一句:如果重要的话我正在使用gcc 4.5.2.

Jam*_*lis 15

问题const typename A<T>::U &x是它U是一个依赖类型,并且编译器不能T从参数中推导出(这是非中断上下文之一).

例如,您可以有两个专业A:

class X { };
class Y { };
class Z { };

template <> class A<X> {
public: 
    typedef Z U;
};

template <> class A<Y> {
public:
    typedef Z U;
};
Run Code Online (Sandbox Code Playgroud)

如果你然后打电话:

Z a;
a == 1;
Run Code Online (Sandbox Code Playgroud)

编译器应该推断出T什么? XY

在这种特殊情况下,一种解决方案是operator==在类模板中声明为非模板的朋友:

template <class T = int>
class A {
public:
    class U {
    };

    friend bool operator==(const U& x, int y) {
        return true;
    }

public:
    U f() const { return U(); }
};
Run Code Online (Sandbox Code Playgroud)

  • @Nawaz:"Z"是否依赖并不重要; 重要的是"U"是依赖的.`Z`可以是任何东西.(我最初使用`int`,但这是错误的,因为函数模板在重载解析期间甚至不会因为内置运算符而被考虑,所以我引入了`Z`作为一个类型而没有`运算符的非模板重载==`). (3认同)

CB *_*ley 11

template <class T>
bool operator==(const typename A<T>::U &x, int y) {
    return true;
}
Run Code Online (Sandbox Code Playgroud)

使用此模板,不允许(或有时可能)T从类型中推导出模板参数x.这就是所谓的不可推导的背景.(例如,某人可以专门A针对不同的参数,比如说doubleA<double>::U为其创建一个typedef A<int>::U.)

没有解决方法,您必须显式指定模板参数,以operator==使其具有丑陋的语法.