【发布时间】:2017-07-29 03:00:48
【问题描述】:
由于模板类型推导的问题,这段代码无法编译,甚至在 C++14 下也无法编译。最不优雅的解决方法是什么?
#include <vector>
#include <functional>
#include <iostream>
template <class T>
std::vector<T> merge_sorted(
const std::vector<T>& a, const std::vector<T>& b,
std::function<bool(const T, const T)> a_before_b)
{
std::vector<T> ret;
auto ia=a.begin();
auto ib=b.begin();
for (;;ia!=a.end() || ib!=b.end())
ret.push_back( a_before_b(*ia,*ib) ? *(ia++) : *(ib++) );
return ret;
}
int main()
{
std::vector<double> A { 1.1, 1.3, 1.8 };
std::vector<double> B { 2.1, 2.2, 2.4, 2.7 };
auto f = [](const double a, const double b) -> bool {
return (a-(long)(a))<=(b-(long(b))); };
std::vector<double> C = merge_sorted(A, B, f);
for (double c: C)
std::cout << c << std::endl;
// expected outout: 1.1 2.1 2.2 1.3 2.4 2.7 1.8
}
这里是来自g++ -std=c++14 main.cpp的错误消息:
main.cpp: In function ‘int main()’:
main.cpp:23:49: error: no matching function for call to ‘merge_sorted(std::vector<double>&, std::vector<double>&, main()::<lambda(double, double)>&)’
std::vector<double> C = merge_sorted(A, B, f);
^
main.cpp:6:16: note: candidate: template<class T> std::vector<T> merge_sorted(const std::vector<T>&, const std::vector<T>&, std::function<bool(T, T)>)
std::vector<T> merge_sorted(
^~~~~~~~~~~~
main.cpp:6:16: note: template argument deduction/substitution failed:
main.cpp:23:49: note: ‘main()::<lambda(double, double)>’ is not derived from ‘std::function<bool(T, T)>’
std::vector<double> C = merge_sorted(A, B, f);
==
稍后编辑,仅作记录:这里有一个可以编译的代码版本(感谢收到的答案)并正确执行(对上述未经测试的代码进行了多次更正):
#include <vector>
#include <functional>
#include <iostream>
template <class T, class Pred>
std::vector<T> merge_sorted(const std::vector<T>& a, const std::vector<T>& b, Pred a_before_b)
{
std::vector<T> ret;
auto ia=a.begin();
auto ib=b.begin();
for (;ia!=a.end() && ib!=b.end();)
ret.push_back( a_before_b(*ia,*ib) ? *(ia++) : *(ib++) );
for (;ia!=a.end();)
ret.push_back( *(ia++) );
for (;ib!=b.end();)
ret.push_back( *(ib++) );
return ret;
}
int main()
{
std::vector<double> A { 1.1, 1.3, 1.8 };
std::vector<double> B { 2.1, 2.2, 2.4, 2.7 };
auto f = [](const double a, const double b) -> bool {
return (a-(long)(a))<=(b-(long(b))); };
std::vector<double> C = merge_sorted(A, B, f);
for (double c: C)
std::cout << c << std::endl;
// expected outout: 1.1 2.1 2.2 1.3 2.4 2.7 1.8
}
【问题讨论】:
-
除非你要把merge_sorted重载到死,否则我只会为a_before_b的类型使用一个单独的模板参数,不需要std::function。
-
@Marc:我不确定我是否理解 - 请您详细说明一下,可能以答案的形式?
-
注意,您可以在
merge_sorted正文中重新使用std::merge。 -
感谢大家的cmets和回答。你让我相信谓词模板参数是要走的路。现在我的代码编译了……我发现它仍然存在缺陷(在达到 b.end() 之后访问 *ib)……但这是一个完全不同的故事。
标签: c++ templates lambda c++14 std-function