题
我希望能够写出类似的东西
char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);
这 transform
函数看起来很相似,但它不会自动生成结果集合的大小。
解决方案
您可以使用 std::back_inserter
在 <iterator>
, ,尽管提供前面的大小更有效。例如:
string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"
其他提示
这个问题是在 C++11 标准生效之前提出的……如今我们有 std::transform()
作为(丑陋的)函数式编程“地图”的等价物。使用方法如下:
auto f(char) -> char; // or if you like: char f(char)
vector<char> bar;
vector<char> foo;
// ... initialize bar somehow ...
std::transform(bar.begin(), bar.end(), std::back_inserter(foo), f);
为了完成这项工作,您需要以下观察结果:
- 为了使作业有效,
map
功能应该 不是 做工作。相反,它应该将其参数保存在临时对象中(就您而言,这将是class map::result<char(*)(char), vector<char> >
) - 这
map::result
临时应该有一个template <typename T> operator T
转换。 - 当。。。的时候
map::result
被分配给std::vector<char>
, ,这种转换是唯一可行的。 - 在转换操作员中
class map::result<char(*)(char), vector<char> >::operator vector<char>
您具有输入和返回类型以及映射功能。此时,您可以有效地转换输入。
<edit>
代码
template<typename CONT, typename FUNC>
class mapresult {
CONT const& in;
FUNC f;
public:
template<typename RESULT> RESULT to() const
{
RESULT out;
for (auto const& e : in) { out.push_back(f(e)); }
return out;
}
template<typename RESULT> operator RESULT() const
{
return this->to<RESULT>();
}
mapresult(CONT const& in, FUNC f) : in(in), f(std::move(f)) { }
};
template<typename CONT, typename FUNC>
auto map(CONT const& in, FUNC f) -> mapresult<CONT, FUNC>
{
return mapresult<CONT, FUNC>(in, f);
}
这样使用:
using namespace std;
char foo(char c) { return c | ('A' ^ 'a'); }
std::string in = "Test";
int main(int argc, char* argv[])
{
string out = map(in, &foo);
cout << out << endl;
char replace = 'e';
cout << map(in, [replace](char c){return c == replace ? '?' : c; }).to<string>();
}
不隶属于 StackOverflow