C++ 变量模板的未声明标识符
我还在学习如何使用可变模板。基本上,我想做的是获取一个C++ 变量模板的未声明标识符,c++,c++11,templates,variadic-templates,template-templates,C++,C++11,Templates,Variadic Templates,Template Templates,我还在学习如何使用可变模板。基本上,我想做的是获取一个STLContainer,它包含String类型的元素。STL容器不接受固定数量的参数,所以我尝试使用可变模板。如果我理解正确,我应该能够写下: /* Take a container of String and return a string of those elements separated by commas.*/ template < template <typename String, typename ... T
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;
}
/*获取一个字符串容器并返回由逗号分隔的元素组成的字符串*/
模板<模板类STLContainer>
字符串作为逗号列表(常量STLContainer和container)
{
字符串结果;
for(auto-it=container.begin();it!=container.end();it++)
{
结果+=*it;
结果+=“,”;
}
result.pop_back();//弹出最后一个逗号
返回结果;
}
然而,编译器(Apple LLVM 8.1.0版
)指出:
错误:使用未声明的标识符“Traits”
非常感谢您的帮助
编辑:我最终选择了@Pixelchemist的答案,因为它似乎是最“通用证明”的解决方案,并提供了对我的代码的洞察。然而,我想说,@Walter的答案相当好。虽然@max66的答案是解决问题的最简单答案,但最初的问题是我试图错误地描述STL容器。怎么办
template <template <typename...> class STLContainer,
typename String, typename Traits>
String as_comma_list(const STLContainer<String, Traits> &container)
那怎么办
template <template <typename...> class STLContainer,
typename String, typename Traits>
String as_comma_list(const STLContainer<String, Traits> &container)
您的代码必须如下所示:
现在,我们尝试将实现为_comma_list
,使用支持ADL的迭代,并且对容器或字符串的模板布局没有任何约束
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;
}
模板
自动作为逗号列表(C&&C)
{
使用std::begin;
使用std::end;
使用字符串\u type=std::decation\u t;
使用char\u type=std::decation\u t;
字符串类型结果;
自动常数ec=结束(c);
对于(自动it=begin(c);it!=ec;)
{
结果+=*it;
如果(++it!=ec)
{
结果+=细节::逗号::c;
}
否则就断了;
}
返回结果;
}
注意:此示例要求字符串类型也是可编辑的(这是非常常见的),并且它在循环中有第二个分支,在这里处理数十亿个字符串时可能会慢一些。您的代码必须如下所示:
现在,我们尝试将实现为_comma_list
,使用支持ADL的迭代,并且对容器或字符串的模板布局没有任何约束
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;
}
模板
自动作为逗号列表(C&&C)
{
使用std::begin;
使用std::end;
使用字符串\u type=std::decation\u t;
使用char\u type=std::decation\u t;
字符串类型结果;
自动常数ec=结束(c);
对于(自动it=begin(c);it!=ec;)
{
结果+=*it;
如果(++it!=ec)
{
结果+=细节::逗号::c;
}
否则就断了;
}
返回结果;
}
注意:此示例要求字符串类型也是iterable(这是非常常见的),并且它在循环中有第二个分支,在这里处理数十亿字符串时可能会较慢。尝试以这种方式编写泛型代码注定会失败,因为在一般情况下,容器不能被描述为
容器,想一想map
,它有value\u type=pair
在C++中,这种泛型编程通常是通过<代码>迭代器< /C> >(如标准库中的所有),例如
模板
在函数体中启用\u if//或使用静态\u assert()
作为逗号列表(开始、结束和结束)
{
字符串结果;
for(;begin!=end;++begin)
{
结果+=*开始;
结果+=“,”;
}
result.pop_back();
返回结果;
}
尝试以这种方式编写通用代码肯定会失败,因为在一般情况下,容器不能被描述为容器
,请考虑映射
,它具有值\u type=pair
在C++中,这种泛型编程通常是通过<代码>迭代器< /C> >(如标准库中的所有),例如
模板
在函数体中启用\u if//或使用静态\u assert()
作为逗号列表(开始、结束和结束)
{
字符串结果;
for(;begin!=end;++begin)
{
结果+=*开始;
结果+=“,”;
}
result.pop_back();
返回结果;
}
Traits
不是一种类型;它是一个参数包。您需要展开参数包:STLContainer
实际上,您也没有参数包;您需要Traits
不在STLContainer
的模板参数列表中,而是在作为逗号列表的STL容器通常不能被描述为container
。考虑<代码> STD::MAP<代码>,它有<代码> ValueOyType=STD::配对< /COD>…>代码>特性> /COD>不是一种类型;它是一个参数包。您需要展开参数包:STLContainer
实际上,您也没有参数包;您需要Traits
不在STLContainer
的模板参数列表中,而是在作为逗号列表的STL容器通常不能被描述为container
。考虑<代码> STD::map < /COD>,它有<代码> ValueOyType=STD::配对< /代码>…有趣的概念,SimpIsiType;-]沃尔特-很有趣,不是吗:(?我已经使用了拼写检查器。谢谢!尽管我必须问一下,参考@Walter的答案。这会捕获所有STL容器吗?我测试了它,编译器成功地推断出STLContainer
是std::vector
而String
是std::String
@CarlosBrito-模板参数部分截取几乎所有STL容器(例外:std::array
,因为它的第二个模板参数不是一个类型);但可能您不希望以相同的方式使用它们;我的意思是:向量和集合的begin()
方法返回一个“指向”所包含(String
)的迭代器元素;用于映射(orde)
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;
}
template<typename It>
enable_if_t<is_same<string, typename iterator_traits<It>::value_type>::value,
string> // or use static_assert() in the function body
as_comma_list(It begin, const It &end)
{
string result;
for(; begin!=end; ++begin)
{
result += *begin;
result += ",";
}
result.pop_back();
return result;
}