我有一组我的头声明这样的功能:具有相同名称和签名的多个功能相互覆盖?
actual_function.hpp
#ifndef ACTUAL_FUNCTION_HPP
#define ACTUAL_FUNCTION_HPP
#include <iostream>
#ifdef CONDITION
#warning Compiling version 1
template<typename T>
T fun (T x) {
std::cout << "Version 1 implementation is called.\n";
return x + x;
}
#else
#warning Compiling version 2
template<typename T>
T fun (T x) {
std::cout << "Version 2 implementation is called.\n";
return 2 * x + 1;
}
#endif
#endif
我想在一个测试程序来测试该函数的两个版本。我以为我可以与多个翻译单位做到这一点,所以我有一个文件布局是这样的:
main.cpp中:
void test_version_1();
void test_version_2();
int main() {
test_version_1();
test_version_2();
return 0;
}
test1.cpp:
#include <cassert>
#include <iostream>
#define CONDITION
#include "actual_function.hpp"
void test_version_1() {
std::cout << "Version 1 is called.\n";
assert (fun (8) == 16);
}
测试2.cpp
#include <cassert>
#include <iostream>
#undef CONDITION
#include "actual_function.hpp"
void test_version_2() {
std::cout << "Version 2 is called.\n";
assert (fun (8) == 17);
}
我的想法是,这会给test1.cpp版本1的乐趣和test2.cpp版本2的乐趣。预处理器输出似乎支持这种想法:
g++ main.cpp test1.cpp test2.cpp
In file included from test1.cpp:4:0:
actual_function.hpp:7:2: warning: #warning Compiling version 1 [-Wcpp]
In file included from test2.cpp:4:0:
actual_function.hpp:14:2: warning: #warning Compiling version 2 [-Wcpp]
但是,我的猜测是,链接器混合了我的东西。当我运行该程序,这是发生了什么:
./a.out
Version 1 is called.
Version 1 implementation is called.
Version 2 is called.
Version 1 implementation is called.
a.out: test2.cpp:7: void test_version_2(): Assertion `fun (8) == 17' failed.
Aborted (core dumped)
如果我只在定义一个命名乐趣别的东西,并调用新命名的功能,一切正常,这表明了正确的功能在正确的位置可见。如果我只在定义处重命名函数,但不改变调用点,则会出现编译器错误test2.cpp:7:2: error: ‘fun’ was not declared in this scope
。这使我认为链接器覆盖了函数,因为它们具有相同的名称和签名。
这是真的吗?如果是这样,最好的解决方案是什么?我的两个想法如下:
1:我的函数需要一个额外的模板参数,所以它会是模板,然后专注于真正与错误。实际上,我可能需要一些比这更复杂的东西(也许专注于一个int或某物),因为我真正的问题有更多的选择。如果定义了CONDITION宏,它将使用手动版本。如果条件宏没有被定义,那么它会查看它是否知道我手动执行的任何编译器内在函数,如果是,它就会使用它们,否则,无论宏是否存在,它都会回到手动定义。不过,某些模板专业化仍然可以在这里工作。
2:使用不同名称创建函数fun_manual
和fun_intrinsic
,并且fun
是一个包装函数,它根据其名称调用它们。我不完全确定这将如何工作。
我主要关心的是,如果编译器不支持内部版本,编译器就无法看到内部版本,否则会给出错误。
我的两个解决方案是我能做的最好的,还是有更好的?
这是未定义的行为,如果不是所有的翻译单位看到完全相同的定义。 – 2012-03-20 22:37:46
你有功能模板,而不是功能。 – 2012-03-20 22:39:01
GCC中是否有警告可以打开以提醒用户多个功能正在合并为一个?修好我的'actual_function.hpp'头后,我仍然得到了同样的错误结果。然后我意识到,在我的代码的另一部分,我忘记了在未命名的名称空间中粘贴一些函数。 – 2012-03-20 23:43:27