我仍在学习如何使用可变参数模板。基本上,我想做的是一个包含STLContainer
类型元素的String
。 STL容器没有固定数量的参数,因此我尝试使用可变参数模板。如果我理解正确,我应该可以这样写:
/* Take a container of String and return a string of those elements separated by commas.*/
template < template <typename String, typename ... Traits > class STLContainer >
String as_comma_list(const STLContainer<String, Traits> &container)
{
String result;
for (auto it = container.begin(); it != container.end(); it++)
{
result += *it;
result += ",";
}
result.pop_back(); // pop last comma
return result;
}
但是,编译器(
Apple LLVM version 8.1.0
)吐出:error: use of undeclared identifier 'Traits'
任何帮助深表感谢。
编辑:我最终选择了@Pixelchemist的答案,因为这似乎是最“通用的证明”解决方案,并且可以深入了解我的代码。但是,我想说@Walter的回答同样好。 @ max66的答案是解决问题的最简单方法,但最初的问题是我试图错误地描述STL容器。
最佳答案
您的代码必须如下所示:
template < template <class...> class STLContainer, class String, class ...Traits>
String as_comma_list(const STLContainer<String, Traits...> &container)
但是让我们看一下代码的含义:
类型
STLContainer
必须带有模板参数。如果我写了一个simplestringvector
类(我知道这不是通用的,但是没有人不能阻止我:),那么您的代码将对我不起作用。STLContainer
类型必须提供begin()
和end()
成员。 (没有免费功能;没有std::begin
和std::end
)String
类型必须提供一个pop_back()
成员。String
类型必须定义为operator+=
,该类型必须能够处理包含char
的字符串文字(无wchar_t
,无char16_t
,...)。还有其他在这里问题不大的问题。
该函数可以更通用:
没有保修,因为我很累,但是无论如何...
如果您的代码无论如何都要求类型是可迭代的,则无需首先知道String的类型。您可以将其作为取消引用容器迭代器的衰减结果而获得。通过将
std::begin
和std::end
拖动到作用域中,可以启用ADL以获得免费的开始和结束功能,同时仍可以通过std函数捕获成员函数。首先是一些标题和一个助手类:
#include <type_traits>
#include <iterator>
namespace detail
{
template<class ...> struct comma;
template<> struct comma<char>
{ static constexpr char c = ','; };
template<> struct comma<wchar_t>
{ static constexpr wchar_t c = L','; };
template<> struct comma<char16_t>
{ static constexpr char16_t c = u','; };
template<> struct comma<char32_t>
{ static constexpr char16_t c = U','; };
}
现在,我们尝试通过启用ADL的迭代来实现
as_comma_list
,并且对容器或字符串的模板布局没有任何限制。template <class C>
auto as_comma_list(C&& c)
{
using std::begin;
using std::end;
using string_type = std::decay_t<decltype(*begin(c))>;
using char_type = std::decay_t<decltype(*begin(*begin(c)))>;
string_type result;
auto const ec = end(c);
for (auto it = begin(c); it != ec; )
{
result += *it;
if (++it != ec)
{
result += detail::comma<char_type>::c;
}
else break;
}
return result;
}
注意:此示例还要求String类型也可迭代(这是非常常见的),并且它在循环中具有第二个分支,在此处处理数十亿个字符串时,它可能会比较慢。
关于c++ - 可变参数模板的未声明标识符,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46247045/