天道酬勤,学无止境

C++ template friend function not linking

I have the following code which compiles in VC6 :

Text.h:

template <typename T>
class CTextT
{
   public:

    friend  CTextT add(const CTextT& text1, const CTextT& text2) ;

friend CTextT operator+(const CTextT& string1, const CTextT& string2)   
    {  
       return ::add(string1, string2);}
    }

    ....................
};

And at the end of the header

 #include "Text.inl"

Text.inl:

template <typename T>
CTextT<T> add(const CTextT<T>& text1, const CTextT<T>& text2) 
{   
    CTextT<T> temp ;

    // do something

    return temp ;
}

But VC2010 gives me LINK error:

error LNK2019: unresolved external symbol "class CTextT<char> __cdecl add(class     CTextT<char> const &,class CTextT<char> const &)" (?add@@YA?AV?$CTextT@D@@ABV1@0@Z)  
referenced in function "class CTextT<char> __cdecl operator+(class CTextT<char> const &,class CTextT<char> const &)" (??H@YA?AV?$CTextT@D@@ABV0@0@Z)

 1>.\Debug\UnitTestText.exe : fatal error LNK1120: 1 unresolved externals

If I place the code in the Text.h it compiles fine. But I do not want to do this because I want to keep declaration clean from implementation. I can't figure why linker is complaining in this case when the function is outside the class? This is the only problem and the class is very big and there are other friend functions returning CTextT.

评论

Of course it does give a linker error. The add() function you made a friend isn't a function template! It is a non-template function declared inside a class template. As a result, you won't be able to define this function as a template, either. You can directly define it at the friend declaration.

The alternative is to declare the function template prior to the class template. Of course, this requires a declaration of the class template, too. The following should work:

template <typename T> class CTextT;
template <typename T> CTextT<T> add(CTextT<T> const&, CTextT<T> const&);
template <typename T>
class CTextT
{
    friend CTextT<T> add<>(CTextT<T> const&, CTextT<T> const&);
    // ...
};

Now the template definition you have give should work.

The solution is following:

template <typename T>
class CTextT
{
public:

template <typename T>
friend CTextT<T> add(CTextT<T> const&, CTextT<T> const&) ;

friend  CTextT<T> operator+(const CTextT<T>& string1, const CTextT<T>& string2)  
{  return ::add(string1, string2); }

};

template <typename T>
CTextT<T> add(CTextT<T> const&, CTextT<T> const&) 
{
   CTextT<T> temp ;
   return temp ;
}

I found the following link to MSDN explaining how to add friend functions in templates - http://msdn.microsoft.com/en-us/library/f1b2td24.aspx.

I tested and it works for VS2010 and VS2012. VC6 does not need the second template declaration (it takes it from the class) and in VC6 this code will not compile anymore - will return INTERNAL COMPILER ERROR.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 在链表程序中使用模板时在 C++ 中重载 << 运算符(Overloading << operator in C++ when using templates in linked list program)
    问题 我正在尝试实现一个链表。 但是当我尝试重载 << 运算符时收到错误。 这是我的程序: #include<iostream> #include<stdlib.h> using namespace std; template<class T> class List; template<class T> class Node { T data; Node* next; public: Node(T val) { data = val; next = NULL; } Node(T val, Node* link) { data = val; next = link; } friend class List<T>; friend ostream& operator<<(ostream& out, List<T>* li); }; template<class T> class List { Node<T>* first; Node<T>* last; public: friend ostream& operator<< (ostream& out, List<T>* li) { if(li->first) out<<"Empty.\n"; else { out<<"Displaying: \n"; Node<T>* p = li->first; while(p) { out<<p-
  • 模板类 C++(template class c++)
    问题 我尝试为我的大学项目设计一个模板。 我写了以下代码: #ifndef _LinkedList_H_ #define _LinkedList_H_ #include "Link.h" #include <ostream> template <class L>//error one class LinkedList { private: Link<L> *pm_head; Link<L> * pm_tail; int m_numOfElements; Link<L>* FindLink(L * dataToFind); public: LinkedList(); ~LinkedList(); int GetNumOfElements(){return m_numOfElements;} bool Add( L * data); L *FindData(L * data); template <class L> friend ostream & operator<<(ostream& os,const LinkedList<L> listToprint);//error two L* GetDataOnTop(); bool RemoveFromHead(); L* Remove(L * toRemove); 此模板使用链接类模板 #ifndef _Link_H_ #define
  • C ++模板好友运算符重载(C++ template friend operator overloading)
    问题 我的代码有什么问题? template<int E, int F> class Float { friend Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs); }; G ++只会发出警告: float.h:7: warning: friend declaration ‘Float<E, F> operator+(const Float<E, F>&, const Float<E, F>&)’ declares a non-template function float.h:7: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning 如警告说明中所述,我试图add <> after the function name here ,但是g ++给了我一个错误。 我用clang ++编译了代码,这很好,完全没有警告。 回答1 这只是有关该语言棘手方面的警告。
  • Overloading << operator in C++ when using templates in linked list program
    I'm trying to implement a linked list. But I'm receiving an error when I try overloading the << operator. This is my program: #include<iostream> #include<stdlib.h> using namespace std; template<class T> class List; template<class T> class Node { T data; Node* next; public: Node(T val) { data = val; next = NULL; } Node(T val, Node* link) { data = val; next = link; } friend class List<T>; friend ostream& operator<<(ostream& out, List<T>* li); }; template<class T> class List { Node<T>* first; Node<T>* last; public: friend ostream& operator<< (ostream& out, List<T>* li) { if(li->first) out<<"Empty
  • Template friend function of a template class
    I was struggling with the issue described in this question (declaring a template function as a friend of a template class), and I believe the 2nd answer is what I want to do (forward declare the template function, then name a specialization as a friend). I have a question about whether a slightly different solution is actually correct or just happens to work in Visual C++ 2008. Test code is: #include <iostream> // forward declarations template <typename T> class test; template <typename T> std::ostream& operator<<(std::ostream &out, const test<T> &t); template <typename T> class test { friend
  • C++服务器开发
    四天计划 学习时候夯实基础 学习时候求甚解,用得时候可以不用理解那么深 在学习其他模块时候学习通用思想,命令 行业共识 day1 1.cout是什么 << 双目运算符,左移运算符 左右都是值,有一种特殊得值,cout本质就是对象 2.让输出得对象合法,那就重载运算符,重要c++编程技巧 重载运算符 ostream 3.左值引用是什么和为什么用const 自己思考 4.当私有变量,重载时候访问不到怎么办,友元函数 友元函数得作用就是使得 一个函数可以访问到对象私有成员属性 工程开发中需要将成员得类设置成私有的 //构造方法,友元,私有属性 几点思考 1.c++中现成的工具和方法,思考这些工具和方法它们是怎么实现的 2,对现有c++知识的掌握和连接,知道语法特性 3.c++程序来讲,工程代码中如何写,满足工程规范 各种规范!! 构造函数,先声明再实现这种规范 c++是极其考验技术想象力的一门语言 四大主流编程范式: 面向过程、面向对象、泛型编程、函数式编程 需要涉猎外部大量知识 //------------暂时下面好像还有问题 //------------暂时上面面好像还有问题 怎么去学习c++ 算法数据结构思维、底层操作系统理解、网络知识巩固 锻炼编程思维 c++语法特性特别多,是为了支持四种编程范式的,可以将不同的语法特性归类到不同的编程范式中 比如说学习c+
  • 模板类的模板朋友功能(Template friend function of a template class)
    问题 我正在解决此问题中描述的问题(将模板函数声明为模板类的朋友),并且我相信第二个答案就是我想要做的事(向前声明模板函数,然后将专门化名称命名为朋友)。 我有一个关于稍微不同的解决方案实际上是正确的还是恰好在Visual C ++ 2008中起作用的问题。 测试代码为: #include <iostream> // forward declarations template <typename T> class test; template <typename T> std::ostream& operator<<(std::ostream &out, const test<T> &t); template <typename T> class test { friend std::ostream& operator<< <T>(std::ostream &out, const test<T> &t); // alternative friend declaration // template <typename U> // friend std::ostream& operator<<(std::ostream &out, const test<T> &t); // rest of class }; template <typename T> std::ostream&
  • C++ List Implementation
    So, I'm building an implementation of List for a programming exercise. So far I have this: #include <iostream> #include <algorithm> using namespace std; template <class T> class Link; template <class T> class List_iterator; template <class T> class List { public: typedef List_iterator<T> iterator; List(); List(const List<T> & l); ~List(); bool empty() const; unsigned int size() const; T & back() const; T & front() const; void push_front(const T & x); void push_back(const T & x); void pop_front(); void pop_back(); iterator begin() const; iterator end() const; void insert(iterator pos, const T &
  • C++ 模板运算符重载(C++ Template operator overload)
    问题 我正在编写一个模板矩阵类,我对重载 * 运算符的工作方式有些困惑。 我想重载这样的东西(省略不相关的代码): template<typename T>class Matrix4t { friend vector3 operator*(const vector3 &inputV3, const matrix4t &inputM4t); template <typename scalarT> friend scalarT operator*(const scalarT &inputSclT, const matrix4t &inputM4t); public: const matrix4t operator*(const matrix4t) vector3 operator*(const vector3 &inputV3); template <typename scalarT> const matrix4t operator*(const scalarT&); } 假设单个乘法的正确定义我认为这应该允许我的矩阵对象与来自操作数两侧的 vector3 类型的对象相乘,每次返回一个 vector3 。 它还应该允许我的矩阵与标量模板值相乘,标量模板值可以是浮点数、双精度等。这些方法的定义需要不同,以允许向量与标量乘法,因此不仅仅是使用模板 但是,在将此运算符与 vector3
  • 深圳大学 C题目和 C++题目答案
    前言 请勿轻易外传,资源宝贵,且用且珍惜 正文 以下为 C 题库截图,仅展示少部分。 C++题库 这里仅列出题目名称,需要的同学与我联系szujrjzh@outlook.com T1 DS图—最小生成树 2.0.cpp T1 DS二叉树——Huffman编码与解码(不含代码框架).cpp T2 图综合练习–构建邻接表.cpp T5 DS图—图的连通分量.cpp T1 DS图—最小生成树 1.0.cpp T1 DS图—最小生成树 3.0.cpp T2 道路建设.cpp T3 图的应用之——图的连通.cpp T4 图的顶点可达闭包.cpp T5 货币套汇.cpp T1 大写字母加密.c T2 晶晶赴约会.c T3 计算两时间的差值.c T4 妹子几点到?.c T5 对齐输出.c T6 算术式子判断.c T7 输出扑克牌.c T8 点和正方形的关系.c T9 求绝对值.c T10 计算两点间的距离.c T11 单词加密.c T12 排序输出.c T13 完数判断.c T14 落地反弹.c T15 勤奋的大佬.c T16 期末评价.c T17 序列求和.c T18 三角形判断.c T19 三角形类型判断.c T1 数石子游戏.c T17 带参数的main函数 宏定义.c T18 int与float与double数据类型所占的字节大小.c T19 链表 学生成绩 例11-8.c T20
  • 2020最新版C/C++学习路线图--C++核心编程与桌面应用开发
    黑马程序员C/C++学习路线图大纲中第三阶段的学习是C++核心编程与桌面应用开发的学习:主要介绍了C/C++学习路线图的C++核心编程与桌面应用开发的学习目标,C/C++学习路线图的C++核心编程与桌面应用开发的市场价值,C/C++学习路线图的C++核心编程与桌面应用开发的重点知识。C/C++学习路线图中的C++核心编程与桌面应用开发学习视频可以在黑马程序员视频库中找到自学教程。 C/C++学习路线图中C++核心编程与桌面应用开发的技术要点:C++对C的扩展、引用;函数重载;类和对象;对象的动态分配和释放;运算符重载;类的继承和派生、多态;函数模板、类模板;异常、I/O流;STL;Qt常用的控件;Qt绘图与文件操作;Qt综合案例实战。 C++对C的扩展、引用 1.C++语言的命名空间的使用 2.C++对C的扩展 3.C、C++中const不同之处 4.定义和使用引用类型变量 5.C++11常用语法 函数重载 1.类的的默认参数 2.c++的函数重载 3.类和对象的基本概念 4.类的封装和访问控制权限 5.类和对象进行简单编程 类和对象 1.类的构造函数 2.类的析构函数 3.explicit关键字作用 4.类的拷贝构造函数的使用 5.深拷贝和浅拷贝问题 6.多个对象的构造和析构函(初始化列表) 对象的动态分配和释放 1.类和对象的动态分配和释放内存 2.静态成员变量和函数的使用 3
  • 将未定义的类设为友元,稍后再定义(Making an undefined class as friend, and defining it later)
    问题 结交不知名的朋友 template<typename T> class List { protected: class a { int x; int y; private: friend class b; // <------------ Why this is not an error? }; template <typename U > class b { //If that is not a error this should be an error int z; U y; }; public: List() { a* ptr = (a *)new unsigned char[sizeof(a)]; } }; int main() { List<int> mylist; } 请通过此链接,我有我的问题作为代码中的评论。 我正在努力让另一个班级成为我班级的朋友。 但是那个班在交朋友的时候是不知道的。 允许它的 C++ 规则是什么。 后来我以这样一种方式定义该类,它与朋友声明不兼容。 为什么不抛出错误。 谢谢 回答1 是的,您的代码无效! 这是一个有趣的展示,展示了模板如何以微妙的方式改变代码的含义。 下面的代码是有效的: class List { public: class a { typedef int type; friend class b; // that's
  • C++运算符==重载[重复](C++ operator== overloading [duplicate])
    问题 这个问题在这里已经有了答案: 9年前关闭。 可能的重复: 运算符重载 以下重载 operator== 的方法有什么区别? // stroustrup way friend bool operator== (MyClass &lhs, MyClass &rhs); 和 // as taught in other places, including caltech bool MyClass::operator== (MyClass &rhs); 哪种方式更好? 回答1 // stroustrup way friend bool operator== (MyClass &lhs, MyClass &rhs); 参数应该是const : friend bool operator==(const MyClass& lhs, const MyClass& rhs); 这是首选,因为它在第一个参数可以隐式构造时起作用。 例如,如果std::string只有一个成员函数operator== ,那么"abc" == my_std_string不会调用它! 但是,可以通过从“abc”隐式构造字符串来调用非成员函数(在这种特殊情况下更好,出于性能原因可以提供单独的bool operator==(const char*, const std::string&) ,但重点仍然存在 -
  • 2020C/C++学习路线图,内附完整自学路线+视频+学习平台
    2020年不平凡的一年,找工作压力也相比较大一些,所以把基础打好,基础好职业之路更稳定长久一些。 有人说:“C生万物,编程之本”,这一点都没有错! C语言是最接近计算机的语言,很多时间,我们都会发现,C语言是非常有必要学习的。 1、 C语言 数据类型、变量、内存布局、指针基础; 字符串、一维数组、二维数组; 一级指针,二级指针,三级指针,N级指针概念,指针数组和数组指针; 结构体、文件的使用; 动态库的封装和设计; 函数指针回调函数。 配套视频: 轻松掌握C语言视频教程(会打字就能学会) 全国计算机等级考试二级c语言视频教61节课 C语言提高深入浅出 七日成蝶之C语言数据结构经典合集高级视频课程 链接: 关注公众号:C语言与CPP编程 回复C语言、c++、电子书获取资料 2、C++初级编程 面向对象编程思想; 类的封装,构造和析构、静态成员、对象管理; 类的构造(有参构造函数、无参构造、拷贝构造、默认构造函数)和析构; 对象动态管理、友元函数、友元类、操作符重载; C++编译器对象管理模型分析; 类对象的动态管理(new/delete); 友元函数和友元类; 运算符重载(一元运算符、二元运算符、运算符重载难点、项目开发中的运算符重载); 类的继承、多继承及其二义性、虚继承; 多态(概念、意义、原理剖析、多态案例); 虚函数、纯虚函数、抽象类(面向抽象类编程思想案例); 函数模板
  • 在没有朋友的情况下在 C++ 中测试私有类成员 [重复](Testing private class member in C++ without friend [duplicate])
    问题 这个问题在这里已经有了答案: 如何测试私有函数或具有私有方法、字段或内部类的类? (57 个回答) 3年前关闭。 今天和一个同事讨论在课堂上是否测试私有成员或私有状态。 他几乎说服了我为什么它是有道理的。 这个问题的目的不是复制已经存在的关于测试私有成员的性质和原因的 StackOverflow 问题,例如:将单元测试作为它正在测试的类的朋友有什么问题? 同事的建议在我看来有点脆弱,将朋友声明引入单元测试实现类。 在我看来这是不行的,因为我们在测试代码中引入了一些测试代码的依赖,而测试代码已经依赖于测试代码 => 循环依赖。 即使像重命名测试类这样无害的事情也会导致单元测试中断,并在测试代码中强制执行代码更改。 我想请 C++ 专家对另一个建议进行判断,该建议依赖于我们可以专门化模板函数这一事实。 想象一下这个类: // tested_class.h struct tested_class { tested_class(int i) : i_(i) {} //some function which do complex things with i // and sometimes return a result private: int i_; }; 我不喜欢为 i_ 设置一个 getter 只是为了让它可测试的想法。 所以我的建议是类中的'test_backdoor
  • NDK开发之C语言基础
    1.NDK开发为什么使用Visual Studio vs方便在电脑中调试,实时看到代码的执行效果,而且和Android studio的环境非常相似,便于移植。一般在visual studio中调试好代码,再导入到Android studio中执行。 2.使用vs怎么创建项目 vs只要是Windows的都可以开发,包括移动和WEB 都可以开发。开发NDK使用社区版,对开发者免费。配置NDK开发需要下载C++的linux开发和Windows版的C++的桌面开发。新建项目选择CMAKE工程,目录外面相当于是工程,里面是model。CMAKELISTS.txt 相当于是build.gradle。运行项目需要先把目录切换到.cpp文件目录,然后点击运行按钮。注:CMAKELISTS.txt文件中不能包含分号。 3.函数 在C语言中,函数为基础,是由函数组成的可执行文件。代码是从上向下执行的,main函数调用的函数必须在main函数的上面或者使用头文件。而在Java中,是面向对象的,会将整个class文件都加载到内存中。头文件相当于接口,只有函数的声明没有实现,用来解决函数的耦合问题。指针函数也是函数,返回类型是某一类型的指针 。eg:void* ap(int a,int b){}。 函数指针是变量,eg:定义 void (*ap)(int a;int b); 赋值ap=ab(函数名称)
  • C ++:朋友声明'声明非模板函数(C++ : friend declaration ‘declares a non-template function)
    问题 我在重载<<流运算符时遇到问题,但找不到解决方案: template<class T, unsigned int TN> class NVector { inline friend std::ostream& operator<< ( std::ostream &lhs, const NVector<T, TN> &rhs); }; template<class T, unsigned int TN> inline std::ostream& NVector<T, TN>::operator<<( std::ostream &lhs, const NVector<T, TN> &rhs) { /* SOMETHING */ return lhs; }; 它产生以下错误信息: 警告:朋友声明'std :: ostream&operator <<(std :: ostream&,const NVector&)'声明一个非模板函数[-Wnon-template-friend] 错误:“ std :: ostream&NVector :: operator <<(std :: ostream&,const NVector&)'必须正好采用一个参数 如何解决这个问题? 非常感谢你。 回答1 您的代码中存在两个不同的问题,第一个问题是friend声明(如警告明确指出的那样
  • 模板的 C++ 类成员访问问题(C++ Class member access problem with templates)
    问题 我遇到了一个问题,如果我有一个模板类,它又具有一个模板方法,该方法采用该类的另一个实例的参数(具有不同的模板参数),则它无法访问作为传递的类的受保护或私有成员一个参数,例如: template<typename T>class MyClass { T v; public: MyClass(T v):v(v){} template<typename T2>void foo(MyClass<T2> obj) { std::cout << v << " "; //error C2248: 'MyClass<T>::v' : cannot access private member declared in class 'MyClass<T>' std::cout << obj.v << " "; std::cout << v + obj.v << std::endl; } }; int main() { MyClass<int> x(5); MyClass<double> y(12.3); x.foo(y); } 有没有办法说 MyClass<T> 中的方法可以完全访问 MyClass<SomeOtherT>? 回答1 它们是不同的类型:模板从模板构造新类型。 您必须对您的班级朋友进行其他实例化: template <typename T>class MyClass { T v
  • 模板对象的模板友元函数和命名空间(template object's template friend functions and namespaces)
    问题 在以下 C++ 示例代码中,GCC 6 和 Clang 3.8 在正确的行为上存在分歧: 这个人为的例子“有效”——就像test()函数在 GCC 中返回op 。 在 clang 中,它调用(未定义)函数get<int, int, float, double> : template<typename ...Args> class obj { bool p = false; template<typename T, typename... Args2> friend T get(const obj<Args2...> &o) { return o.p; } }; template<typename T, typename... Args> T get(const obj<Args...> &o); bool test(const obj<int, float, double> &a) { return get<int>(a); } 将相同的代码放在命名空间中会导致 GCC 做与 clang 相同的事情。 namespace ns { template<typename ...Args> class obj { bool p = false; template<typename T, typename... Args2> friend T get(const obj<Args2
  • C++:运算符<<嵌套类中的重载(C++: operator<< overloading in the nested classes)
    问题 这个问题在这里有一个详细的答案:重载运算符<<:无法将左值绑定到 'std::basic_ostream<char>&&' 我试图重载嵌套子类,并花了一个小时试图重载operator<< 。 在这里研究了一下,但仍然无法解决。 有什么帮助吗? :) 每当我尝试使用g++ -std=c++11 -lm -ggdb -g -O0 -Wall p_7_1.cpp -o p_7_1编译它时,它都会给我一个错误: Undefined symbols for architecture x86_64: "operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, LinkedBinaryTree<int>::Position const&)", referenced from: std::__1::basic_ostream<char, std::__1::char_traits<char> >& operator<<<int>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, LinkedBinaryTree<int> const&) in p_7_1-9fc2c2.o ld: symbol(s) not found for