具有相同名称和签名的多个功能相互覆盖?

Dav*_*one 0 c++ linker c-preprocessor

我有一组函数,我在这样的标题中声明:

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
Run Code Online (Sandbox Code Playgroud)

我试图在一个测试程序中测试该函数的两个版本.我以为我可以用多个翻译单元来做这个,所以我有这样的文件布局:

main.cpp中:

void test_version_1 ();
void test_version_2 ();
int main () {
    test_version_1 ();
    test_version_2 ();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

测试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);
}
Run Code Online (Sandbox Code Playgroud)

我的想法是,这会给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]
Run Code Online (Sandbox Code Playgroud)

但是,我的猜测是链接器正在混淆我.当我运行程序时,会发生以下情况:

./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)
Run Code Online (Sandbox Code Playgroud)

如果我只在其中一个定义中重命名其他内容,并调用新命名的函数,一切都按预期工作,这表明正确的函数在正确的位置可见.如果我只在定义中重命名一个函数,但不改变调用点,则会出现编译错误test2.cpp:7:2: error: ‘fun’ was not declared in this scope.这让我觉得链接器覆盖了函数,因为它们具有相同的名称和签名.

这真的是发生了什么?如果是这样,最佳解决方案是什么?我的两个想法如下:

1:让我的函数采用额外的模板参数,因此它将是模板,然后专注于true和false.实际上,我可能需要比这更复杂的东西(可能专注于int或其他东西),因为我的真正问题还有一些选择.如果定义了CONDITION宏,则它使用手动版本.如果未定义条件宏,那么它会看到它是否知道任何编译器内在函数执行我手动执行的操作,如果是,它会使用它们,否则,无论宏是否存在,它都会依赖于手动定义.但是,某种模板专业化仍然可以在这里工作.

2:创建具有不同名称的功能fun_manualfun_intrinsic,并有fun是要求根据它们的名称的包装函数.我不完全确定这是如何工作的.

我主要担心的是,如果编译器不支持内部版本,编译器就看不到内部版本,否则会产生错误.

我的两种解决方案中的任何一种都是我能做的最好的,还是有更好的东西?

Mar*_*som 5

您违反了" 一个定义规则".基本上,允许编译器和链接器的组合将函数的不同版本视为相同.