模板、函数重载及其出现顺序
Templates, function overloading and their order of appearence
我试图为这个问题做一个简化版本的代码。在这个过程中,我遇到了一些对我来说没有意义的事情。有人能解释一下为什么我得到以下结果吗?下面是代码,它应该在gcc中编译和运行。
#include <string>
#include <iostream>
#include <typeinfo>
using std::string;
template <typename T> inline char getType(const T&) {return 'S'; }
inline char getType(const char&) {return 'C';}
template <typename T> inline char getType(T*) {return 'A'; }
template <typename T> inline void writeData(const T& x) {
printf("Calling default writeData...n");
char type = getType(x);
if (type == 'S') {
printf("ERROR: binaryWrite::writeData -> Structure not defined.n");
exit(1);
}
std::cout << x << std::endl;
}
template <typename T> inline void writeData(T* x, const unsigned int& len) {
printf("Writing array with writeData...n");
char type = getType(x[0]);
std::cout << len << std::endl;
if (type == 'S') {
for (int i=0; i < len; ++i) {
writeData(x[i]);
}
} else {
for (int i=0; i < len; ++i) {
std::cout << x[i] << std::endl;
}
}
}
class binaryWrite {
public:
binaryWrite(void) {}
template <typename T>
void write(const T& x, const char* name) {
writeData(x);
}
};
inline void writeData(const string& s) {
unsigned int len = s.size();
const char* pt = s.c_str();
writeData(pt, len);
}
int main () {
string str = "Hello World";
writeData(str);
binaryWrite BF;
BF.write(str, "str");
return 0;
}
输出:
manuel-lopezs-macbook-pro:binaryFiles jmlopez$ g++ -o example example.cpp
manuel-lopezs-macbook-pro:binaryFiles jmlopez$ ./example
Writing array with writeData...
11
H
e
l
l
o
W
o
r
l
d
Calling default writeData...
ERROR: binaryWrite::writeData -> Structure not defined.
首先用字符串版本调用writeData
。在我尝试调用binaryWrite
函数write
(此函数调用writeData
)后,它调用模板定义的函数。
我摆弄了一下,发现如果我把字符串的重载函数移到binaryWrite
的类定义上方,那么我就得到了我想要的结果。
这是改变:
inline void writeData(const string& s) {
unsigned int len = s.size();
const char* pt = s.c_str();
writeData(pt, len);
}
class binaryWrite {
public:
binaryWrite(void) {}
template <typename T>
void write(const T& x, const char* name) {
writeData(x);
}
};
输出
Writing array with writeData...
11
H
e
l
l
o
W
o
r
l
d
Writing array with writeData...
11
H
e
l
l
o
W
o
r
l
d
在第一种情况下,binaryWrite
似乎不知道string
的重载函数writeData
。但是在转换之后,因为我先定义了重载函数,所以它知道。这个解释正确吗?
我最终想做的是将宏WRITESTRUCT
用于其他类型,但此定义将在其他一些文件中,因此我将无法在binaryWrite
的定义之前编写它们。如果我的解释是正确的,有什么办法可以解决这个问题吗?
好吧,玩你的代码,我发现它也执行正确,如果你移动所有的writeData
模板和重载binaryWrite
类定义以下。
当编译器遇到binaryWrite::write
时,它检查是否有writeData
的定义。此时它选择template <typename T> inline void writeData(const T& x)
,因为它只能访问前两个模板。然后,它再也不会回去看看是否有更好的选择。
当您将writeData模板移动到binaryWrite之后时,编译器没有writeData的定义,并决定在模板实例化期间再次查找。所以当你使用binaryWrite::write
时,它会选择直接重载,而不是模板。
您的三个函数是:
template <typename T> inline void writeData(const T& x);
template <typename T> inline void writeData(T* x, CIX len);
inline void writeData(const string& s);
我不知道为什么template<typename T> void write(const T& x, const char* name)
决定第三个选项不够好,但是如果你把第三个选项变成writeData
的模板专门化,而不是重载,问题就会消失:
template <> inline void writeData<string>(const string& s);
同时,去掉那些宏。我看不出WRITESTRUCT(string, s)
如何比void writeData(const std::string& s)
更清晰,特别是因为没有涉及结构体。
是的,正确的解决方案是移动重载的函数,或者至少是它的声明,这样它对binaryWrite是可见的。
一些编译器不能正确地做这件事,并且在考虑的重载集合中包含在binaryWrite之后但在其使用之前声明的函数。如果不同位置的可见函数集不相同,这会导致有趣的ODR冲突。
- 函数调用中参数的顺序重要吗
- 优先顺序:智能指针和类析构函数
- C++成员的析构函数顺序与shared_ptr
- C++:使用方法调用析构函数的顺序是什么?
- 以 f() + g() 调用顺序的 C++ 函数
- 为什么用户定义的函数不按照给定的顺序对相同长度的元素进行排序?
- 有没有办法保证析构函数的相对顺序?
- 函数模板实例化、替换和重载解析的顺序是什么?
- 类内初始化与构造函数初始化列表的顺序
- 递归函数的执行顺序
- 运算符 new 的执行顺序和构造函数的参数
- 如果在 C++ 构造函数中以错误的顺序初始化对象数据,会发生什么类型的错误
- std::bind() 参数列表中函子的执行顺序(可能与函数参数的求值顺序无关)
- 构造函数中没有参数的对象类成员按什么顺序初始化?
- std::unique_ptr析构函数顺序
- C++17的可选和可变顺序函数参数
- OpenMP 不在 for 循环中的顺序函数的并行化
- 递归C++字母顺序函数重复返回相同的值
- C++-销毁顺序-函数的静态成员在主类析构函数之前被销毁
- 构造函数执行顺序/顺序:函数中静态变量(类实例)的依赖初始化