如何实现这样的模板专业化
How to implement template specialization like this?
现在,我使用的函数'JoinStrings'只能联接数据类型std::string。我现在需要加入integer。所以我希望重构它,但我失败了。我很高兴听到"你不能这样做",因为我真的不知道以这种方式重用这些代码是否合理。
调用部分:
int main(int argc, char* argv[]) {
vector<int> integers;
string str = JoinStrings(integers);
cout << str << endl;
}
我未能实现的部分:
#include <string>
template <class ConstForwardIterator>
void JoinStrings(const ConstForwardIterator& begin,
const ConstForwardIterator& end,
const std::string& delimiter,
std::string* output) {
output->clear();
for (ConstForwardIterator iter = begin; iter != end; ++iter) {
if (iter != begin) {
output->append(delimiter);
}
output->append(*iter);
}
}
// What data type should be declared for IntegerConstForwardIterator?
template<>
void JoinStrings(const IntegerConstForwardIterator& begin,
const IntegerConstForwardIterator& end,
const std::string& delimiter,
std::string* output) {
output->clear();
for (IntegerConstForwardIterator iter = begin; iter != end; ++iter) {
if (iter != begin) {
output->append(delimiter);
}
output->append(std::to_string(*iter));
}
}
template <class ConstForwardIterator>
std::string JoinStrings(const ConstForwardIterator& begin,
const ConstForwardIterator& end,
const std::string& delimiter) {
std::string output;
JoinStrings(begin, end, delimiter, &output);
return output;
}
template <class Container>
std::string JoinStrings(const Container& container,
const std::string& delimiter = " ") {
return JoinStrings(container.begin(), container.end(), delimiter);
}
可以修改代码来实现您想要的。我将这个问题解释为模板专业化练习。(对于推荐的替代方案,请关注日本政府的评论)
前言:我本以为这会奏效,但(尽管它编译了)没有,因为通用版本仍然更匹配:
template<template <class> class Cont >
void JoinStrings(const typename Cont<int>::const_iterator& begin,
const typename Cont<int>::const_iterator& end,
const std::string& delimiter,
std::string* output) {
std::clog << "specialized called" << std::endl;
....
}
因此,我不得不求助于好的旧enable_if
(为了简洁起见,我在这里使用c++11,经过一些努力,可以将其转换为c++98)。使用您的main
代码,将调用专用版本。
解决方案
#include<type_traits>
....
template <class ConstForwardIterator,
class = typename std::enable_if<not std::is_same<typename std::decay<decltype(*std::declval<ConstForwardIterator>())>::type, int>::value>::type
>
void JoinStrings(const ConstForwardIterator& begin,
const ConstForwardIterator& end,
const std::string& delimiter,
std::string* output) {
std::clog << "generic called" << std::endl;
std::clog << std::trace() << std::endl;
}
template <class ConstForwardIterator,
class = typename std::enable_if<std::is_same<typename std::decay<decltype(*std::declval<ConstForwardIterator>())>::type, int>::value>::type,
class Tag = void
>
void JoinStrings(const ConstForwardIterator& begin,
const ConstForwardIterator& end,
const std::string& delimiter,
std::string* output) {
std::clog << "special called" << std::endl;
....
}
一个更经典的解决方案是使用"标记调度"http://www.boost.org/community/generic_programming.html#tag_dispatching,但这需要更改更多的代码,如JoinString的Container版本。
受限解决方案:如果您希望代码仅适用于std::vector
,则解决方案要简单得多:
template <>
void JoinStrings(const std::vector<int>::const_iterator& begin,
const std::vector<int>::const_iterator& end,
const std::string& delimiter,
std::string* output)
这就是您想要的吗?正如@jogojapan所说,使用std::ostringstream是一个更好的选择。
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
template <class ConstForwardIterator>
std::string JoinStrings(const ConstForwardIterator& begin,
const ConstForwardIterator& end,
const std::string& delimiter) {
std::ostringstream oss;
for (ConstForwardIterator iter = begin; iter != end; ++iter) {
if (iter != begin) {
oss << delimiter;
}
oss << *iter;
}
return oss.str();
}
template <class Container>
std::string JoinStrings(const Container &container,
const std::string& delimiter = " ") {
return JoinStrings(container.begin(),
container.end(), delimiter);
}
int main(int argc, char *argv[]) {
std::vector<int> integers;
integers.push_back(1);
integers.push_back(2);
integers.push_back(3);
std::string str = JoinStrings(integers);
std::cout << str << std::endl;
std::vector<std::string> strings;
strings.push_back("MOU");
strings.push_back("BI");
str = JoinStrings(strings);
std::cout << str << std::endl;
return 0;
}
相关文章:
- 如果没有malloc,链表实现将失败
- 如何使用默认参数等选择模板专业化
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 模板化建造师专业化
- 使用简单类型列表实现的指数编译时间.为什么
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 类模板的成员功能的定义在单独的TU中完全专业化
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- Python中的for循环与C++有何不同
- 如何正确实现和访问运算符的各种自定义枚举器
- 如何在部分类模板专业化中实现继承
- c++中两种形式的专业化模板实现之间的区别是什么
- 类模板专业化可以利用非专业化实现吗
- 模板专业化实现
- 如何实现这样的模板专业化
- 我的 PRNG 实现与我尝试复制的实现有何不同?