潜在的 g++模板错误?

发布于 2024-10-11 22:44:35 字数 1269 浏览 1 评论 0原文

我遇到过一些我认为应该编译的代码,但实际上没有。所以我希望 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;
}

所以,来描述这里发生的事情。我有一个类模板 (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'

这看起来很奇怪,因为我清楚地(我认为)定义了一个模板化的operator==这应该涵盖这一点,事实上,如果我只为编译器做一些工作(启用 USE_FIX),那么我就不会再收到错误。不幸的是,“修复”并不通用,仅适用于模板的特定实例。

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

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

I've encountered some code which I think should compile, but doesn't. So I'm hoping some of the local standards experts here at SO can help :-).

I basically have some code which resembles this:

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

So, to describe what is going on here. I have a class template (A) which has an internal class (U) and at least one member function which can return an instance of that internal class (f()).

Then I am attempting to create an operator== function which compares this internal type to some other type (in this case an int, but it doesn't seem to matter).

When USE_FIX is not defined I get the following error:

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

Which seems odd, because I am clearly (I think) defining a templated operator== which should cover this, in fact if I just do a little of the work for the compiler (enable USE_FIX), then I no longer get an error. Unfortunately, the "fix" doesn't work generically, only for a specific instantiation of the template.

Is this supposed to work as I expected? Or is this simply not allowed?

BTW: if it matters I am using gcc 4.5.2.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时光暖心i 2024-10-18 22:44:35

const typename A::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;
};

如果您随后调用:

Z a;
a == 1;

编译器应将 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(); }
};

The problem with const typename A<T>::U &x is that U is a dependent type and the compiler cannot deduce T from the argument (this is one of the nondeduced context).

You could, for example, have two specializations of A:

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

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

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

If you then call:

Z a;
a == 1;

what should the compiler deduce T as? X? Y?

One solution in this particular case is to declare operator== as a nontemplate friend inside of the class template:

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(); }
};
咽泪装欢 2024-10-18 22:44:35
template <class T>
bool operator==(const typename A<T>::U &x, int y) {
    return true;
}

使用此模板,不允许(或有时不可能)从 x 的类型推导模板参数 T。这就是所谓的不可演绎上下文。 (例如,有人可以将 A 专门用于不同的参数,例如 double 并使 A::U 成为 AA;int>::U。)

没有解决方法,您必须显式指定模板参数,这对于 operator== 来说会产生丑陋的语法。

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

Using this template, it is not permissible (or sometimes possible) to deduce the template parameter T from the type of x. It is what is known as a non-deducible context. (E.g. Somebody could specialize A for a different parameter, say double and make A<double>::U a typedef for A<int>::U.)

There is no workaround, you would have to explicitly specify the template parameter which for operator== makes for ugly syntax.

归途 2024-10-18 22:44:35

由于相当明显的原因,这是不允许的。在一般情况下,编译器实际上无法从对运算符 == 的调用中推断出模板参数。显然,您假设嵌套类型 U 唯一定义了封闭的 A 专业化。事实并非如此,可以通过以下示例来说明,其中包含 A 的两个显式特化。

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

template <> class A<double> {
public:
  typedef A<int>::U U;
};

在这种情况下,如果您使用 == 类型的参数调用模板化运算符 == code>A::U 编译器无法推导模板化运算符 == 的模板参数 TT 应该是 int 还是 double?没有办法说。

为了避免这些歧义,这种情况被称为“非推导上下文”。从嵌套类型推导封闭类模板参数是非推导上下文的一个示例。

It is not allowed for rather obvious reasons. In general case there's really no way the compiler can deduce the template argument from your call to operator ==. Apparently you assumed that the nested type U uniquely defines the enclosing A specialization. That is not true, which can be illustrated by the following example with two explicit specializations of A

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

template <> class A<double> {
public:
  typedef A<int>::U U;
};

In this case, if you call templated operator == with an argument of type A<int>::U the compiler cannot deduce template argument T for templated operator ==. Should T be int or double? There's no way to say.

In order to avoid these ambiguities such situations are called non-deduced contexts. Deducing the enclosing class template arguments from a nested type is an example of non-deduced context.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文