潜在的 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;
}
所以,来描述这里发生的事情。我有一个类模板 (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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
const typename A::U &x
的问题在于U
是依赖类型,编译器无法从中推导出T
论证(这是非推导的上下文之一)。例如,您可以拥有
A
的两个特化:如果您随后调用:
编译器应将
T
推导为什么?X
?Y
?这种特殊情况下的一种解决方案是将
operator==
声明为类模板内的非模板友元:The problem with
const typename A<T>::U &x
is thatU
is a dependent type and the compiler cannot deduceT
from the argument (this is one of the nondeduced context).You could, for example, have two specializations of
A
:If you then call:
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:使用此模板,不允许(或有时不可能)从
x
的类型推导模板参数T
。这就是所谓的不可演绎上下文。 (例如,有人可以将A
专门用于不同的参数,例如double
并使A::U
成为A
A
;int>::U
。)没有解决方法,您必须显式指定模板参数,这对于
operator==
来说会产生丑陋的语法。Using this template, it is not permissible (or sometimes possible) to deduce the template parameter
T
from the type ofx
. It is what is known as a non-deducible context. (E.g. Somebody could specializeA
for a different parameter, saydouble
and makeA<double>::U
a typedef forA<int>::U
.)There is no workaround, you would have to explicitly specify the template parameter which for
operator==
makes for ugly syntax.由于相当明显的原因,这是不允许的。在一般情况下,编译器实际上无法从对运算符
==
的调用中推断出模板参数。显然,您假设嵌套类型U
唯一定义了封闭的A
专业化。事实并非如此,可以通过以下示例来说明,其中包含A
的两个显式特化。在这种情况下,如果您使用::U 编译器无法推导模板化运算符
==
类型的参数调用模板化运算符==
code>A==
的模板参数T
。T
应该是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 typeU
uniquely defines the enclosingA
specialization. That is not true, which can be illustrated by the following example with two explicit specializations ofA
In this case, if you call templated operator
==
with an argument of typeA<int>::U
the compiler cannot deduce template argumentT
for templated operator==
. ShouldT
beint
ordouble
? 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.