c++ - 内联函数在链接期间发生冲突?

标签 c++ function linker inline

我在头文件中定义了一个函数模板,并在几个源文件中使用了它。当我链接程序时,出现以下错误:

Linking ....................... ./Release_gcc_lin64_5534_ST/tom 
/mxhome/charrison/git/sdcore/libs/CommUtils/Release_gcc_lin64_5534_ST/libCommUtils.so(Block.o): In function `wd_sprintf_r(boost::basic_format<char, std::char_traits<char>, std::allocator<char> > const&)':
/mxhome/charrison/git/sdcore/libs/CommUtils/include/wd_sprintf.h:29: multiple definition of `wd_sprintf_r(boost::basic_format<char, std::char_traits<char>, std::allocator<char> > const&)'
./Release_gcc_lin64_5534_ST/tom.o:/mxhome/charrison/git/sdcore/libs/CommUtils/include/wd_sprintf.h:29: first defined here
/mxhome/charrison/git/sdcore/libs/CommUtils/Release_gcc_lin64_5534_ST/libCommUtils.so(MemRef.o): In function `wd_sprintf_r(boost::basic_format<char, std::char_traits<char>, std::allocator<char> > const&)':
/mxhome/charrison/git/sdcore/libs/CommUtils/include/wd_sprintf.h:29: multiple definition of `wd_sprintf_r(boost::basic_format<char, std::char_traits<char>, std::allocator<char> > const&)'
./Release_gcc_lin64_5534_ST/tom.o:/mxhome/charrison/git/sdcore/libs/CommUtils/include/wd_sprintf.h:29: first defined here

我不明白这是怎么回事。大概这些函数是内联的,那么如何防止目标文件中的多个实例发生冲突?

这是包含函数定义的头文件:

wd_sprintf.h:

#ifndef WDSPRINTF_H
#define WDSPRINTF_H

#include <string>
#include <sstream>
#include <boost/format.hpp>

// This is what the recursive template function wd_sprintf_r devolves
// to..
std::string 
wd_sprintf_r(const boost::format &boost_format) {

    std::stringstream s;
    s << boost_format;
    return std::move(s.str()); // force move semantics
}

// wd_sprintf_r(format, args...): 
//
// This unpacks the variadic arguments one at a time, recursively.  It
// binds the first arg to the pattern, and if there are remaining
// variadic arguments, it calls itself.  Otherwise it calls the above.
template <typename T, typename... Params>
std::string 
wd_sprintf_r(boost::format &boost_format, 
         const T &arg, const Params&... parameters) {

    return wd_sprintf_r(boost_format % arg, parameters...); 
}

// wd_sprintf(pattern [,args...]): 
//
// This creates a temporary boost::format from pattern, and calls
// wd_sprintf_r() to recursively extract and apply arguments.

#include <boost/exception/all.hpp>

class wd_sprintf_exception : public std::runtime_error {
public:
    wd_sprintf_exception(std::string const& msg) : std::runtime_error(msg) {};
};

template <typename... Params>
std::string 
wd_sprintf (const std::string &pat, const Params&... parameters) {
    try {
        boost::format boost_format(pat);
        return wd_sprintf_r(boost_format, parameters...);
    }
    catch ( boost::io::format_error& e) {
        const std::string what = std::string("wd_sprintf: ") + std::string(e.what());
        throw wd_sprintf_exception(what);
    }
}

#endif

最佳答案

函数模板不是问题 - 它们的定义必须出现在使用它们的每个翻译单元中(除非显式实例化),并且由编译器来安排它以便链接器满意与它。

但是,您还有一个非模板函数,它遵循正常规则。您必须将其定义(= 主体)移至源文件并在 header 中仅保留一个声明,或者将其定义保留在 header 中并将其标记为 inline。当标记为 inline 时,它必须再次出现在使用它的每个翻译单元中(但这正是将要发生的事情),并且一切都会起作用。

关于c++ - 内联函数在链接期间发生冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22389458/

相关文章:

c - 将无符号字符数组作为参数传递 - 数组未正确传递

dynamic - 如何仅将动态符号保留在共享对象中以进行动态链接?

solr - 获取构面名称以及有关 Solr 中字段的额外/元信息

c++ - 静态工厂方法和静态对象内存泄漏

c++ - 对指针列表进行排序

php - 从类内的函数传递变量并在类外回显

MySQL:查询并不总是返回多个商店的最新最低价格

c++ - 在类中声明但未定义的方法

C++ 模板和派生类成员初始化

c++ - 非聚合不能用初始化列表初始化