Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 潜在g++;模板错误?_C++_Templates_G++ - Fatal编程技术网

C++ 潜在g++;模板错误?

C++ 潜在g++;模板错误?,c++,templates,g++,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

我遇到了一些我认为应该编译的代码,但是没有。因此,我希望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;
}
这看起来很奇怪,因为我(我认为)明确地定义了一个模板化的
操作符==
,应该涵盖这一点,事实上,如果我只为编译器做了一点工作(启用使用修复),那么我就不会再收到错误。不幸的是,“修复”一般不起作用,只适用于模板的特定实例化

这应该像我预期的那样有效吗?还是根本不允许这样做


顺便说一句:如果重要的话,我使用的是GCC4.5.2。

constTypeName 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;
};
编译器应该将
T
推断为什么<代码>X<代码>Y

在这种特殊情况下,一种解决方案是将
操作符==
声明为类模板内的非模板朋友:

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(); }
};
模板
甲级{
公众:
U类{
};
友元布尔运算符==(常量U&x,整数y){
返回true;
}
公众:
U f()常量{return U();}
};
模板
布尔运算符==(常量类型名A::U&x,整数y){
返回true;
}
使用此模板时,不允许(或有时可能)从
x
类型推断模板参数
T
。这就是所谓的不可推断的上下文。(例如,有人可以将
A
专门化为不同的参数,比如说
double
,并将
A::U
作为
A::U
的typedef)


没有解决方法,您必须显式指定模板参数,因为
运算符==
会导致语法难看。

这是不允许的,原因很明显。在一般情况下,编译器实际上无法从调用操作符
==
推断模板参数。显然,您假定嵌套类型
U
唯一地定义了封闭
A
专门化。这是不正确的,下面的例子可以用两个显式的
A

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

template <> class A<double> {
public:
  typedef A<int>::U U;
};
模板类别A{
公众:
类U{};
};
模板类别A{
公众:
类型定义A::U;
};
在这种情况下,如果使用类型为
A::U
的参数调用模板运算符
==
,编译器将无法为模板运算符
==
推导模板参数
T
T
应该是
int
还是
double
?没办法说


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

这是不允许的。如果我对您的问题了解得更多,我可以建议您进行适当的重新设计。此问题可能与此问题重复:已被问了很多次,但如果不使用“nondeduced”关键字,您将无法找到任何答案。但是如果你知道关键词,你可能知道答案。。。搜索很困难:[@Matthieu:但希望我们最终建立足够多的副本,以便搜索能够找到它们!@James:顺便说一句,
Z
应该在类模板中声明,只有这样他的情况和您的示例才能结合在一起。您怎么说?我的意思是,
Z
独立于
A
,而
U
In问题是一种依赖类型。@Nawaz:Z是否依赖并不重要;
U
是否依赖重要。
Z
可以是任何东西。(我最初使用的是
int
,但这是错误的,因为内置运算符在重载解析过程中甚至不会考虑函数模板,所以我引入了
Z
作为一种类型,它没有
运算符==
的非模板重载)@James:我的意思是,这一行
za;
应该写成
typename a::U a;
typename a::U a;
来精确指出你的例子与他的情况的相似性!@Nawaz:虽然这可能会让普通读者更容易理解,但事实是它们是100%等效的,而且编译器er一点也不在乎。
typename A::U A;
之后,
typename A::U
Z
是同一个确切类型的别名,这正是无法推断该类型的原因。@David:我知道
typename A::U A;
Z A;
是完全相同的,正如你所说的,这就是为什么要使用该类型的原因
operator=
中的
T
无法推导。但这两种语法对程序员(而不是编译器)有区别,因为synax
typename A::U A;
让程序员相信编译器可以从
A
操作符==
推断出类型
T
。我相信这就是为什么主题启动者认为它可能是编译器本身的一个bug,而不是他的代码!!这就是我想说的全部。:-)我认为这个解释比詹姆斯的解释好。简洁而准确
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(); }
};
template <class T>
bool operator==(const typename A<T>::U &x, int y) {
    return true;
}
template <> class A<int> {
public:
  class U {};
};

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