有关 c++ 中模板上的重载运算符的一些编译器错误;

发布于 2024-09-29 06:31:20 字数 4016 浏览 7 评论 0原文

我有一些代码有一些错误,我根本不明白如何修复。我问了我的教授和助教,并查阅了互联网,除了更准确地理解错误的含义之外,没有运气。据我所知,编译器要么将我的重载运算符与内置运算符混淆,要么根本不将其识别为重载运算符。

我收到以下错误和警告:

||=== project 4, Debug ===|
\project 4\forest.h|13|warning: friend declaration 'Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&)' declares a non-template function|

\project 4\forest.h|13|note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) |

\project 4\forest.h|14|warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Forest<NODETYPE>&)' declares a non-template function|

\project 4\forest.h|15|warning: friend declaration 'std::istream& operator>>(std::istream&, Forest<NODETYPE>&)' declares a non-template function|

\project 4\main.cpp||In function 'int main()':|
\project 4\main.cpp|21|error: ambiguous overload for 'operator>>' in 'file >> intForest'|

c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|119|note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|

c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|123|note:                 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|

c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|130|note:                 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|
||=== Build finished: 1 errors, 3 warnings ===|

当我尝试编译代码时。相关代码段如下:(

在forest.h中)

template< typename NODETYPE > class Forest
{

    public:
        friend Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&);
        friend ostream& operator<<(ostream&, const Forest<NODETYPE>&);
        friend istream& operator>>(istream&, Forest<NODETYPE>&);

        Forest();
        Forest( const Forest& otherForest);
        ~Forest();
        void nodes(int&) const;

    private:
        ForestNode<NODETYPE> *root;

        ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};

(在forest.cpp中)

template<typename NODETYPE> istream& operator>>(istream& file, const Forest<NODETYPE>& f1)
{
    istream file2 = file;
    int nodeCount = 0;
    string blah = ' ';

    while(getline(file2,blah))
    {
        nodeCount++;
    }

    ForestNode<NODETYPE> *forestNodeArray[nodeCount];//holds pointers to last node of depth i

    getline(file,*f1.root.tag);
    forestNodeArray[0] = &(*f1.root);
    inputHelper(file, 0, *f1.root, forestNodeArray, nodeCount);

    return file;
}

(最后在main.cpp中)

int main()
{

    Forest < char > intForest();
    filebuf fb;
    fb.open ("forest1.txt",ios::in);
    istream file(&fb);


    cout << typeid(intForest).name() << endl;
    cout << typeid(file).name() << endl;

    file >> intForest;

    fb.close();


}

任何帮助将不胜感激。

编辑:感谢 alex 和 alf,我明白为什么它们不被视为模板函数。回想起来很明显,我只是决定了这些签名。无论如何,我仍然收到有关不明确运算符的错误。为什么编译器无法识别我的运算符并使用它,而不是尝试在不可能有​​一个参数为 Forest 的运算符的 3 个内置版本之间做出决定?

I have some code with a few errorr I do not understand how to fix at all. I have asked my professor and TA, and consulted the internet with no luck, apart from understanding more precisely what the errors mean. From what I can tell, the compiler is either confusing my overloaded operator with built in operators, or it is not recognizing it as an overloaded operator at all.

I am getting the following errors and warnings:

||=== project 4, Debug ===|
\project 4\forest.h|13|warning: friend declaration 'Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&)' declares a non-template function|

\project 4\forest.h|13|note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) |

\project 4\forest.h|14|warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Forest<NODETYPE>&)' declares a non-template function|

\project 4\forest.h|15|warning: friend declaration 'std::istream& operator>>(std::istream&, Forest<NODETYPE>&)' declares a non-template function|

\project 4\main.cpp||In function 'int main()':|
\project 4\main.cpp|21|error: ambiguous overload for 'operator>>' in 'file >> intForest'|

c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|119|note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|

c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|123|note:                 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|

c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\istream|130|note:                 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>|
||=== Build finished: 1 errors, 3 warnings ===|

When I try to compile my code. The relevant code segments are as follows:

(in forest.h)

template< typename NODETYPE > class Forest
{

    public:
        friend Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&);
        friend ostream& operator<<(ostream&, const Forest<NODETYPE>&);
        friend istream& operator>>(istream&, Forest<NODETYPE>&);

        Forest();
        Forest( const Forest& otherForest);
        ~Forest();
        void nodes(int&) const;

    private:
        ForestNode<NODETYPE> *root;

        ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};

(in forest.cpp)

template<typename NODETYPE> istream& operator>>(istream& file, const Forest<NODETYPE>& f1)
{
    istream file2 = file;
    int nodeCount = 0;
    string blah = ' ';

    while(getline(file2,blah))
    {
        nodeCount++;
    }

    ForestNode<NODETYPE> *forestNodeArray[nodeCount];//holds pointers to last node of depth i

    getline(file,*f1.root.tag);
    forestNodeArray[0] = &(*f1.root);
    inputHelper(file, 0, *f1.root, forestNodeArray, nodeCount);

    return file;
}

(and finally, in main.cpp)

int main()
{

    Forest < char > intForest();
    filebuf fb;
    fb.open ("forest1.txt",ios::in);
    istream file(&fb);


    cout << typeid(intForest).name() << endl;
    cout << typeid(file).name() << endl;

    file >> intForest;

    fb.close();


}

Any help would be greatly appreciated.

EDIT: Thanks to alex and alf, I understand why they were not considered template functions. It's quite obvious in retrospect, I was just set on those signatures. Anyway, I still get the error about the ambiguous operator. Why does the compiler not recognize my operator and use it, instead of trying to decide between 3 built in versions of the operator that could not possibly have one parameter as Forest?

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

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

发布评论

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

评论(3

放低过去 2024-10-06 06:31:20

第二个错误位于这一行:

Forest < char > intForest();

一开始这可能会令人惊讶,但该行并未声明 Forest 类型的变量,而是声明一个不带参数并返回 的函数>森林
只需从声明中删除括号:

Forest < char > intForest;

在第一个警告上,这已经被解释过(声明为朋友的函数不是模板,这意味着您必须手动为用于实例化 Forest< 的每种类型实现它;> with (可能您不希望这样)。另请注意,声明模板化 operator+ ,然后将模板设为友元,如 @Alf P. Steinbach 答案中所示: Forest 将是 Forest 的友元,这可能不是您所需要的 @Alex 提案,只会进行特定的实例化。模板是一个友元,这可能更接近您想要的,但是您需要在模板类之前声明模板化运算符,为此您需要向前声明模板类...

友元自由函数的常见模式模板正在就地定义函数:

template <typename T>
class Forest {
   // ...
   friend Forest& operator+( Forest const & lhs, Forest const & rhs ) [1]
   {
       // implementation here
   }
}
// [1] Note that the arguments are const references (read only), and also note that
//     you do not need to provide the type argument inside the template declaration

这允许您将其定义为非模板化函数,同时让编译器为您实例化该函数。此外,在处理模板时,在类定义中内嵌成员方法通常会更简单。它使生活变得更简单,毕竟在大多数情况下,您确实需要在(同一)头文件中提供实现。

然而,在定义二元运算符时,更好的方法是将 operator+= 定义为成员方法,然后您可以轻松地将 operator+ 定义为非友元自由函数。模式是:

struct test {
   test& operator+=( test const & );
};
test operator+( test lhs, test const & rhs ) { // [2]
   lhs += rhs;
   return lhs;
}
// [2] Note that the first argument is by value, and the second by const reference
//     This means that the compiler will copy the first argument for you, and you
//     are free to modify it with the += operator and return the copy.

现在,最棘手的部分是混合前两个建议。为了能够在模板定义中定义作为自由函数的 operator+,一个常见的技巧是使其成为友元,即使由于访问原因不需要这样做:

template <typename T>
class Forest {
   Forest& operator+=( Forest const & ) {
      // implemenation
   }
   friend Forest operator+( Forest lhs, Forest const & rhs ) { // [3]
      return lhs+=rhs;
   }
};
// [3] friendship only to allow us to define the free function inside the template
//     declaration.

The second error is in this line:

Forest < char > intForest();

This may be surprising at first, but that line is not declaring a variable of type Forest<char>, but rather a function that takes no arguments and returns a Forest<char>.
Just remove the parenthesis from the declaration:

Forest < char > intForest;

On the first warning, which is already explained (the function declared as friend is not a template, and that means that you will manually have to implement it for each type you use to instantiate Forest<> with (probably you don't want that). Also note that declaring the templated operator+ and then making the template a friend as in @Alf P. Steinbach answer means that a Forest<int> will be a friend of a Forest<double>, which might not be what you need. @Alex proposal in the comment will only make a particular instantiation of the template a friend, which is probably closer to what you want, but you need to declare the templated operator before the template class, and for that you will need to forward declare the template class...

A common pattern for friend free functions in templates is defining the function in place:

template <typename T>
class Forest {
   // ...
   friend Forest& operator+( Forest const & lhs, Forest const & rhs ) [1]
   {
       // implementation here
   }
}
// [1] Note that the arguments are const references (read only), and also note that
//     you do not need to provide the type argument inside the template declaration

This allows you to define it as a non templated function and at the same time have the compiler instantiate the function for you. Also, it is usually simpler to also define member methods inlined in the class definition when dealing with templates. It makes life simpler, and after all in most cases you do need to provide the implementation in the (same) header file.

Yet, when defining binary operators a better approach is to define operator+= as a member method, and then you can easily define operator+ as a non-friend free function. The pattern would be:

struct test {
   test& operator+=( test const & );
};
test operator+( test lhs, test const & rhs ) { // [2]
   lhs += rhs;
   return lhs;
}
// [2] Note that the first argument is by value, and the second by const reference
//     This means that the compiler will copy the first argument for you, and you
//     are free to modify it with the += operator and return the copy.

Now, the most tricky part is mixing the previous two advices. To be able to define operator+ that is a free function inside the template definition, a common trick is to make it friend even if that is not required for access reasons:

template <typename T>
class Forest {
   Forest& operator+=( Forest const & ) {
      // implemenation
   }
   friend Forest operator+( Forest lhs, Forest const & rhs ) { // [3]
      return lhs+=rhs;
   }
};
// [3] friendship only to allow us to define the free function inside the template
//     declaration.
屋檐 2024-10-06 06:31:20

(第一个)警告告诉您 befriended 函数不是模板。

但事实并非如此。

考虑一下你将如何实施它。这需要为每种可能的 NODE_TYPE 编写一个这样的函数。

有几种方法可以解决这个问题。

一种方法是与函数模板成为朋友,如下所示:

template< class Type >
struct S
{
    template< class U > friend void foo( S<U> );
};

template< class Type >
void foo( S< Type > x ) {}

int main()
{}

Cheers &呵呵,,

The (first) warning tells you that the befriended function is not a template.

And it isn't.

Think about how you would implement it. It would entail writing one such function for each possible NODE_TYPE.

There are several ways to fix that.

One way is to befriend a function template, like so:

template< class Type >
struct S
{
    template< class U > friend void foo( S<U> );
};

template< class Type >
void foo( S< Type > x ) {}

int main()
{}

Cheers & hth.,

不乱于心 2024-10-06 06:31:20

学习C++,我也遇到了同样的问题。但是我已经用另一种方式解决了!

template <class NODETYPE> class Forest;
template <class NODETYPE> Forest<NODETYPE>& operator+ (Forest<NODETYPE>&, Forest<NODETYPE>&);
template <class NODETYPE> ostream& operator<<(ostream&, const Forest<NODETYPE>&);
template <class NODETYPE>  istream& operator>> (istream&, Forest<NODETYPE>&);
template<class NODETYPE>
template< typename NODETYPE >
class Forest
{

    public:
        friend Forest<NODETYPE>& operator+ <>(Forest<NODETYPE>&, Forest<NODETYPE>&);
        friend ostream& operator<< <>(ostream&, const Forest<NODETYPE>&);
        friend istream& operator>> <>(istream&, Forest<NODETYPE>&);

        Forest();
        Forest( const Forest& otherForest);
        ~Forest();
        void nodes(int&) const;

    private:
        ForestNode<NODETYPE> *root;

        ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};

learning C++,I also encountered the same problem.But I had solved it for another way!

template <class NODETYPE> class Forest;
template <class NODETYPE> Forest<NODETYPE>& operator+ (Forest<NODETYPE>&, Forest<NODETYPE>&);
template <class NODETYPE> ostream& operator<<(ostream&, const Forest<NODETYPE>&);
template <class NODETYPE>  istream& operator>> (istream&, Forest<NODETYPE>&);
template<class NODETYPE>
template< typename NODETYPE >
class Forest
{

    public:
        friend Forest<NODETYPE>& operator+ <>(Forest<NODETYPE>&, Forest<NODETYPE>&);
        friend ostream& operator<< <>(ostream&, const Forest<NODETYPE>&);
        friend istream& operator>> <>(istream&, Forest<NODETYPE>&);

        Forest();
        Forest( const Forest& otherForest);
        ~Forest();
        void nodes(int&) const;

    private:
        ForestNode<NODETYPE> *root;

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