我在类中定义了三个可变参数模板函数作为静态方法。比我决定将它们移动到命名空间。当class-solution编译并按预期工作时,命名空间方法无法编译。
这是基于工作阶段的解决方案:
#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...);
}
};
在这两种情况下, encode 的使用方式如下:
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检查。
答案 0 :(得分:4)
只需要在非变量template
表单之前移动encode
形式的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);
}