gpt4 book ai didi

c++ - 命名空间和类中的可变参数模板函数

转载 作者:太空狗 更新时间:2023-10-29 20:51:36 27 4
gpt4 key购买 nike

我在类中定义了三个可变参数模板函数作为静态方法。然后我决定将它们移动到命名空间。命名空间方法编译失败,而类解决方案编译并按预期工作。

这是基于 worker 类(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.

显式定义 encode(int, uint, double) 时会出现同样的错误:

template std::string sample::encode<int, uint, double>(int a, uint b, double c);

当给出单个参数时,首先使用模板encode(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);
}

关于c++ - 命名空间和类中的可变参数模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49343525/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com