c++ - 我在模板类中有多个 * 运算符的重载。当我将声明以不同的顺序放置时,为什么会得到不同的结果?
问题描述
我有一个需要多个 * 运算符重载的类。其中一些需要声明为朋友,以便我可以将类类型作为第二个参数。这是一个遇到我即将提出的问题的类的示例:
#pragma once
template<typename T>
class Example;
template<typename T>
Example<T> operator*(T value, Example<T> obj);
template<typename T>
class Example
{
private:
T m_data;
public:
Example(T);
friend Example operator*<T>(T, Example);
Example operator*(const T& other);
};
template<typename T>
Example<T> operator*(T value, Example<T> obj)
{
return value * obj.m_data;
}
template<typename T>
Example<T>::Example(T data) :m_data(data) { }
template<typename T>
Example<T> Example<T>::operator*(const T& other)
{
return Example(m_data * other.m_data);
}
这有效,但如果我改变:
template<typename T>
class Example
{
private:
T m_data;
public:
Example(T);
friend Example operator*<T>(T, Example);
Example operator*(const T& other);
};
和
template<typename T>
class Example
{
private:
T m_data;
public:
Example(T);
Example operator*(const T& other);
friend Example operator*<T>(T, Example);
};
即使我所做的只是交换包含运算符重载声明的那两行,我也开始收到一堆错误。你能解释一下这里发生了什么吗?这对我来说毫无意义。
产生错误的代码:
Example<int> a(2);
2 * a;
错误:
unexpected token(s) preceding';' syntax error missing':' before '<' 'operator*': redefinition: previous definition was 'function' 'operator*': looks like a function but there is no parameter list. '*': uses 'Example<int>' which is being defined '*': friend not permitted on data declarations
解决方案
您的代码中有两种不同的名称operator*
。有你之前声明的函数模板,Example
以及 的成员函数Example
。syntaxoperator*<T>
是一种模板特化,仅在operator*
引用模板时有效,对成员函数无效。在您的第一个声明中,在friend
成员函数之前,operator*
成员函数尚未在编译器看到的位置声明operator*<T>
,因此它将名称解析为之前声明的函数模板Example
,一切都很好(具体的特化operator*<T>
变成friend
了每个Example<T>
)。
template<typename T>
Example<T> operator*(T value, Example<T> obj); // <-\ ...finds a template, so no syntax error
// |
template<typename T> // |
class Example { // |
T m_data; // |
public: // |
Example(T); // |
friend Example operator*<T>(T, Example); // >-/ looking up this name...
Example operator*(const T& other);
};
以另一种方式进行操作,而是operator*<T>
引用不是模板的成员函数,并且您会收到语法错误(具体来说,我认为它试图以某种方式将其解释为operator* < T >
实际<
小于>
/大于运算符)。
template<typename T>
class Example {
T m_data;
public:
Example(T);
Example operator*(const T& other); // <-\ ...does not find a template; ouch!
friend Example operator*<T>(T, Example); // >-/ looking up this name...
};
推荐阅读
- mysql - 无法在 Google Cloud SQL 上导入 SQL 文件
- swift - 在 Swift 中格式化秒表的时间
- r - 添加行并有条件地更新以下行
- bash - WSL Ubuntu:出错时停止执行函数
- neo4j - neo4j 还没有开始
- javascript - HTML 中的 Vue 绑定和 CSS 不起作用
- ios - IOS从url设置UITableView背景图片
- javascript - Google Scripts / Sheets 在数据输入单元格后添加前缀
- apache-kafka - Axon 事件通过 EventBus 多次发布
- angular - http 请求何时阻塞 Angular 渲染?