命名空间和类中的可变参数模板函数
Variadic template functions in namespace and in class
我将类中的三个可变参数模板函数定义为静态方法。比我决定将它们移动到命名空间。命名空间方法无法编译,而类解决方案按预期编译和工作。
这是基于工人阶级的解决方案:
#include <list>
#include <string>
class sample
{
public:
template<typename T>
static std::string encode(T t) {
/* do something useful with t */
return std::string("encoded value");
}
template<typename... Ts>
static std::string encode(Ts... ts) {
std::list<std::string> values;
return encode(values, ts...);
}
template<typename T, typename... Ts>
static std::string encode(std::list<std::string>& values, T t, Ts... ts) {
values.push_back(encode(t));
return encode(values, ts...);
}
};
以下是命名空间中的类似定义:
#include <list>
#include <string>
namespace sample
{
template<typename T>
std::string encode(T t) {
/* do something useful with t */
return std::string("encoded value");
}
template<typename... Ts>
std::string encode(Ts... ts) {
std::list<std::string> values;
return encode(values, ts...);
}
template<typename T, typename... Ts>
std::string encode(std::list<std::string>& values, T t, Ts... ts) {
values.push_back(encode(t));
return encode(values, ts...);
}
};
在这两种情况下,编码都按以下方式使用:
std::string encoded = sample::encode(1, 2u, 3.0);
命名空间方法失败,并显示以下错误(第一行缩短(:
sample_namespace.hpp: In instantiation of ‘std::__cxx11::string sample::encode(Ts ...) [with Ts = {std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, ...
sample_namespace.hpp:18:22: recursively required from ‘std::__cxx11::string sample::encode(Ts ...) [with Ts = {std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, int, unsigned int, double}]’
sample_namespace.hpp:18:22: required from ‘std::__cxx11::string sample::encode(Ts ...) [with Ts = {int, unsigned int, double}]’
sample_namespace.hpp:17:32: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
std::list<std::string> values;
^~~~~~
compilation terminated.
显式定义编码(int, uint, double( 时也会发生同样的错误:
template std::string sample::encode<int, uint, double>(int a, uint b, double c);
当给出单个参数时,首先使用模板进行编码(T t(并编译代码。
为什么放置在命名空间中的模板失败?
上面的代码是(不是(用 gcc 6.4.0 x86_64编译的。我还尝试在启用 C++14 和 C++17 的情况下编译它。
代码也无法使用 gcc 7.3、clang 6.0.0 和 icc 18 编译 - 通过 godbolt.org 检查。
只需要将encode
的可变参数template
形式移动到非可变参数template
形式之前。 处理非成员函数时,顺序比成员函数重要得多。 Godbolt 接受以下内容:
#include <list>
#include <string>
namespace sample
{
template<typename T>
std::string encode(T t) {
/* do something useful with t */
return std::string("encoded value");
}
template<typename T, typename... Ts>
std::string encode(std::list<std::string>& values, T t, Ts... ts) {
values.push_back(encode(t));
return encode(values, ts...);
}
template<typename... Ts>
std::string encode(Ts... ts) {
std::list<std::string> values;
return encode(values, ts...);
}
};
std::string do_it() {
return sample::encode(1, 2u, 3.0);
}
相关文章:
- 将可变参数函数的参数封装在类实例中
- QML 使用带有参数C++函数
- 使用可变参数函数作为模板参数
- 如何在C++中伪造虚拟可变参数函数模板?
- 为什么可变参数函数不适用于模板
- C++ std::functional 中的可变参数函数模板
- 可变参数函数指针的定义对于VxWorks spyLib来说不清楚
- 使用可变参数函数覆盖具有不同函数签名的虚函数
- 考虑引用和常量的可变参数函数包装器
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 在可变参数函数中转发特定范围的参数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 使用带有一个参数函数的递归找到数字的平方
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 多个可变参数函数的单个模板参数包?
- 参数数据类型未知的可变参数函数
- 可变参数函数参数包扩展
- 使用模板可变参数函数将多个参数传递给另一个函数
- 对可变参数函数的递归调用的链接器错误
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类