现在,我使用的函数'JoinStrings'只能加入数据类型std :: string。我现在需要加入整数。所以我希望能够重构它。但我失败了。我很高兴听到“你不能这样做”,因为我真的不知道以这种方式重用这些代码是否合理。
调用部分:
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);
}
答案 0 :(得分:0)
可以修改代码以实现您想要的效果。我将此问题解释为模板专业化练习。 (有关推荐的替代方案,请遵循jogojapan的评论)
前言:我希望这可行,但(虽然它会编译)但并不是因为通用版本仍然是更好的匹配:
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,但这需要更改更多代码,例如您的Container-version of JoinString。
受限制的解决方案:如果您希望代码仅适用于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)
答案 1 :(得分:0)
#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;
}