正确声明模板化运算符<<(basic_ostream< charT、特征>、myClass<T > ) 作为朋友

Correctly declaring templated operator<<( basic_ostream< charT, traits >, myClass< T > ) as a friend

本文关键字:lt gt 特征 myClass 朋友 charT basic 声明 运算符 ostream      更新时间:2023-10-16

我正在尝试提高对模板的理解。作为测试,我想超载流operator<<,以便它将在模板类上与STL的(模板)basic_ostream一起运行。这是一个最小示例:

#include <iostream>
using namespace std;
//Forward declarations
template< typename T >
class Container;
template< typename T, typename charT, typename traits >
basic_ostream< charT, traits >& 
    operator<<( basic_ostream< charT, traits >& out, 
                               const Container< T >& a_container ); 
//Definitions
template< typename T >
class Container
{
public:
    Container( T a_value ): value( a_value ){}
private:
    T value;
    template< typename charT, typename traits >
    friend basic_ostream< charT, traits >& 
        operator<<( basic_ostream< charT, traits >& out, 
                    const Container< T >& a_container );
};
template< typename T, typename charT, typename traits >
basic_ostream< charT, traits >& 
    operator<<( basic_ostream< charT, traits >& out, 
                const Container< T >& a_container )
{
    out << a_container.value;
    return out;
}
//Main
int main( void )
{
    Container< int > my_container( 42 );
    cout << my_container;
    return 0;
}

但是,当我尝试编译此代码时,链接器似乎找不到超载函数:

/home/Ae6PGM/cc5xj2iM.o: In function `main':
prog.cpp:(.text.startup+0x21): undefined reference to `std::basic_ostream<char,
std::char_traits<char> >& operator<< <char, std::char_traits<char> >
(std::basic_ostream<char,     std::char_traits<char> >&, Container<int> const&)'
collect2: error: ld returned 1 exit status

如果我将operator<<过载的每个模板实例作为朋友,我可以解决此错误,但是只有与容器类型匹配的实例是朋友,这似乎更正确。这是工作的链接,但不正确的方面:http://ideone.com/dnqzlb。

另一种选择是将函数定义放置在类声明中,但是如果可能的话,我想避免使用。

这里有一个类似但更简单的问题。有一个很好的答案,但我不知道如何适应我的问题。

谢谢,

安德鲁

模板的原始声明采用了三个模板参数{ T, charT, traits },但friend声明仅占2 { charT, traits }。您将获得一个不确定的参考,因为编译器将其视为两个单独的功能,其中一个尚未定义。

您需要给它一个第三模板参数:

template< typename T2, typename charT, typename traits >
    friend basic_ostream< charT, traits >& 
        operator<< ( basic_ostream< charT, traits >& out, 
                    const Container< T2 >& a_container );

谢谢您问这个问题。我通过审查它学到了很多。

也就是说,我想我理解您要问什么。如果我正确理解您,您将尝试通过您的功能模板实现和控制隐式实例。

尽管您在此处发布的示例是operator<< Overloading,但对于函数模板实现了此通用编程的基础机制是相同的。

陈述cout << my_container时,您正在实例化的是过载的operator<<。但是,如果要实例化非模板流对象,则必须修改要从中读取的内容。

由于类数据成员值是私有的,因此您可以使用指针明确指向该数据成员,并使用该指针实例化非网板流对象。以以下示例查看:
int* private_value = (int*)&my_container;
尽管封装,*private_value应该允许您访问私人成员。

如果要增强数据成员的安全性,则需要更深入的封装以防止这种实现。

模板参数可以通过包括get()函数并访问value来实现(如果是您正在寻找的话),从而实例化了非template流对象。