【问题标题】:unable to access friend function in template class无法访问模板类中的好友功能
【发布时间】:2018-11-23 17:46:51
【问题描述】:

Pairwise 类表示具有键:值的对。我制作了一个模板对,但在尝试使用类的键和值输入运行并将其打印出来时出错。

鉴于我的主要:

#include "file_name.h"

int main (){
    Pairwise<string, string> example = {{"key", "value"}};
    cout << example << endl;
 }

还有我的头文件:

#pragma once

#include<iostream>
using std::ostream; using std::cout; using std::endl;
#include<string>
using std::string;
#include<utility>
using std::pair;
#include<sstream>
using std::ostringstream;

template<typename K, typename V>
struct Pairwise{
    K first;
    V second;
    Pairwise() = default;
    Pairwise(K, V);
    //print out as a string in main
    friend ostream& operator<<(ostream &out, const Pairwise &n) {
        ostream oss;
        string s;
        oss << n.first + ":" + n.second; //possible error?
        s = oss.str();
        out << s; 
        return out;
    }
};

运行 main 后我的预期输出是:

key:value

但是,我收到了错误:

h:28:11: error: 'std::basic_ostream<_CharT, _Traits> is protected within..."

【问题讨论】:

  • 那个流插入器有点复杂。 out &lt;&lt; n.first &lt;&lt; ":" &lt;&lt; n.second; return out; 就足够了。事实上,我只想把它写成单行:return out &lt;&lt; n.first &lt;&lt; ':' &lt;&lt; n.second;,但有些人喜欢更冗长。
  • ostream oss; 是一个错字,对吧?应该是ostringstream oss;。并且错误消息被截断。不要总结;发布您能想出的显示问题的最小代码,并引用整个错误消息。这里没有任何受保护的东西,所以错误消息的那部分需要上下文才能有意义。
  • 除了不必要的复杂... oss &lt;&lt; n.first + ":" + n.second; – 为什么+?这将其功能限制为支持 + 本身和字符串文字的类型。
  • @PeteBecker 很棒,缩短的代码总是对我有帮助!
  • @Swordfish 感谢您指出“+”运算符。我一直在寻找改进代码的方法。你认为我的主要功能看起来还不错吗?将值传递给模板类

标签: c++ friend ostream


【解决方案1】:

h:25:59: 朋友声明 delares 一个非模板函数。

您没有将函数声明为采用Pairwise&lt;K, V&gt; 的模板:

header.h:

#ifndef HEADER_H_INCLUDED  /* or pragma once */
#define HEADER_H_INCLUDED  /* if you like it */

#include <iostream>  // or <ostream>

template<typename K, typename V>
class Pairwise {  // made it a class so that the
    K first;      // friend actually makes sense.
    V second;

public:
    Pairwise() = default;

    Pairwise(K first, V second)
    : first{ first }, second{ second }
    {}

    template<typename K, typename V>
    friend std::ostream& operator<<(std::ostream &out, Pairwise<K, V> const &p)
    {
        return out << p.first << ": " << p.second;
    }
};

#endif /* HEADER_H_INCLUDED */

源文件:

#include <iostream>  // the user can't know a random header includes it
#include <string>

#include "header.h"

int main()
{
    Pairwise<std::string, std::string> p{ "foo", "bar" };
    std::cout << p << '\n';
}

旁注:你也可以使用

{
    using Stringpair = Pairwise<std::string, std::string>;
    // ...
    Stringpair sp{ "foo", "bar" };
}

如果您需要更频繁的话。

您得到的其他错误是由于混淆了std::ostringstreamoperator&lt;&lt;() 中的std::ostream

【讨论】:

    【解决方案2】:

    在您编写它时,您将运算符定义为成员函数,这很可能不是有意的。像...一样划分它

    template<typename K, typename V>
    struct Pairwise{
        K first;
        V second;
        Pairwise() = default;
        Pairwise(K, V);
        //print out as a string in main
        friend ostream& operator<<(ostream &out, const Pairwise &n);
    };
    
    template<typename K, typename V>
    ostream& operator<<(ostream &out, const Pairwise<K,V> &n) {
        ...
        return out;
    }
    

    它应该可以工作。

    顺便说一句:请注意,struct 中的所有成员默认都是公开的;这样即使没有friend-声明,您也可以访问它们。

    【讨论】:

    • 用模板在运算符之前
    • 朋友声明前面不是少了template吗?例如template&lt;typename K, typename V&gt; friend ostream&amp; operator&lt;&lt;(ostream &amp;out, const Pairwise&lt;K, V&gt; &amp;n);?
    • 非常感谢,这让我对朋友运营商的理解有了清晰的认识!顺便问一下,你能快速浏览一下我的主要内容吗?如果正确传入值
    • 在你写它的时候,你将操作符定义为一个成员函数——一个带有friend的定义永远不会定义一个成员。
    • @Swordfish 是指“h:25:59:friend declaration delares a non template function...”的警告。您介意在另一篇回答文章中写下您将如何实施该更改吗?似乎这导致我不能完全打印出我的输出“key:value”
    【解决方案3】:

    在 C++ 中,少即是多……

    #pragma once
    
    #include<iostream>
    #include<string>
    
    // never do this in a header file:
    // using std::ostream; 
    
    template<typename K, typename V>
    struct Pairwise{
        K first;
        V second;
        Pairwise() = default;
        Pairwise(K, V);
        //print out as a string in main
        friend std::ostream& operator<<(std::ostream &out, const Pairwise &n) {
            return out << n.first << ':' << n.second;
        }
    };
    
    int main (){
        using std::cout; using std::endl; using std::string;
    
        Pairwise<string, string> example = {"key", "value"};
        cout << example << endl;
     }
    

    https://godbolt.org/z/ZUlLTu

    【讨论】:

      猜你喜欢
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 2021-08-05
      • 2021-11-15
      相关资源
      最近更新 更多