带有void类型和参数的C++11模板专用化

C++11 template specialization with void type and argument

本文关键字:专用 C++11 void 类型 参数 带有      更新时间:2023-10-16

C++11程序中,我定义了以下模板:

namespace outcome {
template <class T>
class c_out {
public:
bool success = false;
std::string error = "";
T result;
};
template <class T>
c_out<T> failed(T res, const std::string& error_msg = "") {
c_out<T> outcome;
outcome.success = false;
outcome.error = error_msg;
return outcome;
};
template <class T>
c_out<T> succeeded(T res) {
c_out<T> outcome;
outcome.success = true;
outcome.result = res;
return outcome;
};
};

类Tvoid时,我想专门化它们。对于c_out:来说,它很容易实现

template <>
class c_out<void> {
public:
bool success = false;
std::string error = "";
};

然而,我在其他两个函数中不断出现错误。我怎样才能把它们专门化?

c_out<void> failed(const std::string& error_msg = "") {
c_out<void> outcome;
outcome.success = false;
outcome.error = error_msg;
return outcome;
};
c_out<void> succeeded(void) {
c_out<void> outcome;
outcome.success = true;
return outcome;
};

错误:当我调用时

outcome::succeeded();

YYY.cpp中,我在链接库时出错:

lib/libXXX.a(YYY.cpp.o): In function `outcome::failed(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
YYY.cpp:(.text+0x0): multiple definition of `outcome::failed(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
CMakeFiles/ZZZ.dir/main/main.cpp.o:main.cpp:(.text+0x0): first defined here
lib/libXXX.a(YYY.cpp.o): In function `outcome::succeeded()':
YYY.cpp:(.text+0x50): multiple definition of `outcome::succeeded()'
CMakeFiles/ZZZ.dir/main/main.cpp.o:main.cpp:(.text+0x50): first defined here

这些不是专业化。这些都是过载。它们是正则函数,这一点很重要,因为函数模板专门化默认情况下有一些正则函数没有的属性。

例如,模板可以出现在页眉中,因此可以在多个翻译单元中定义而不会出现问题。模板是隐式内联。正则函数需要显式内联。

您的错误表明您在头文件中定义了这些重载。将它包含在多个翻译单元中会导致出现多个定义,并且函数不是内联的,所以这是一个格式错误的程序。

解决方案是将这些重载移动到一个专用的TU,并且只公开它们的声明。或者你可以在标题中内联标记它们:

inline c_out<void> failed(const std::string& error_msg = "") {
c_out<void> outcome;
outcome.success = false;
outcome.error = error_msg;
return outcome;
};
inline c_out<void> succeeded(void) {
c_out<void> outcome;
outcome.success = true;
return outcome;
};

这将在每个TU中吐出一个内联定义。只要所有的定义完全相同(对于头中的函数也是如此(,程序就会形成良好的格式。

1.请确保编译时不要使用不同的文件。例如,如果您将模板类放入一个头文件,将main放入另一个.cpp文件,这可能会导致程序崩溃,因为它正在.cpp文件中搜索模板,而上面给出的情况是不存在的。这可能是问题的原因。

  1. 有些IDE没有这个问题,所以您可能想尝试另一个IDE,并检查是否出现相同的错误