【问题标题】:how can i avoid the compiler error: std::transform?如何避免编译器错误:std::transform?
【发布时间】:2012-10-06 14:39:15
【问题描述】:

这是我的 C++ 代码(我使用的是 Visual C++ 2010):

int absd(int t)
{
    return abs(t);
}
int main()
{
    try
    {
        int dpi = 137;
        int dpiCriterionAry[] = {100, 150, 200, 300, 400, 500, 600};
        std::vector<int> vec(dpiCriterionAry, dpiCriterionAry + _countof(dpiCriterionAry));
        std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus<int>(), dpi));
        std::transform(vec.begin(), vec.end(), vec.begin(), absd);
        //std::transform(vec.begin(), vec.end(), vec.begin(), abs);
        copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, "\t"));
        cout << endl;
    }
    catch(exception& e)
    {
        cerr << e.what() << endl;
    }
    return 0;
}

当我取消注释该行时:

//std::transform(vec.begin(), vec.end(), vec.begin(), abs);

我收到错误消息:

1>------ Build started: Project: Console, Configuration: Release Win32 ------ 
1>Build started 2012/10/16 21:17:19. 1>InitializeBuildStatus: 1>  Creating "..\Intermediate\Console.unsuccessfulbuild" because "AlwaysCreate" was specified. 1>ClCompile: 1>  Console.cpp
1>Console.cpp(16): error C2780: '_OutIt std::transform(_InIt1,_InIt1,_InIt2,_OutIt,_Fn2)' : expects 5 arguments - 4 provided 
1>          D:\ProgramFiles\VS 2010\VC\include\algorithm(1155) : see declaration of 'std::transform'
1>Console.cpp(16): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous 
1>Console.cpp(16): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous 
1>Console.cpp(16): error C2784: '_OutIt std::transform(_InIt,_InIt,_OutIt,_Fn1)' : could not deduce template argument for '_OutIt' from 'std::_Vector_iterator<_Myvec>' 
1>          with 
1>          [ 
1>              _Myvec=std::_Vector_val<int,std::allocator<int>> 
1>          ] 
1>          D:\ProgramFiles\VS 2010\VC\include\algorithm(1051) : see declaration of 'std::transform' 
1> 
1>Build FAILED. 
1> 
1>Time Elapsed 00:00:02.48 ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

但是,代码行:

std::transform(vec.begin(), vec.end(), vec.begin(), absd);

可以工作。事实上,我使用的是同一个函数:abs,我对结果感到困惑。 另外,我想知道是否可以将以下两行代码合并为一个(即一个std::transform调用,效果相同):

std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus<int>(), dpi));
std::transform(vec.begin(), vec.end(), vec.begin(), absd);

谁能帮我解决这两个问题?

【问题讨论】:

  • 重载函数不能很好地用作泛型上下文中的函数指针。自从您使用 VS2010 以来最简单的解决方案:使用 lambda。 std::transform(vec.begin(), vec.end(), vec.begin(), [&amp;](int i){ return abs(dpi-i); });

标签: c++ visual-c++ stl compiler-errors genetic-algorithm


【解决方案1】:

问题是std::absseveral overloads。这就是为什么编译器无法确定您在 std::transform 函数调用中尝试使用的重载。

为了修复它,您可以执行@Xeo 在他的评论中提到的操作:

std::transform(vec.begin(), vec.end(), vec.begin(), [&](int i){ return abs(i); });

或者你可以静态转换来获得合适的函数地址:

std::transform(vec.begin(), vec.end(), vec.begin(), static_cast<int(*)(int)>(abs));

关于你的最后一个问题,是的,lambda 在这里很有魅力:

std::transform(vec.begin(), vec.end(), vec.begin(), [&](int i) { return absd(dpi - i); } );

【讨论】:

  • 你太棒了,你能告诉我第二个问题的解决方案吗:我想知道是否可以将以下两行代码合并为一个(即一个 std::transform 调用,效果相同):std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus(), dpi)); std::transform(vec.begin(), vec.end(), vec.begin(), absd);
  • @Triumphant 当然,你去。
【解决方案2】:

abs 是一个重载函数,而不是单个实体,因此对 std::transform 的调用无法推导出模板参数,因为没有一个名为 abs 的函数引用。

相当于这样:

void foo(int) { }
void foo(const char*) { }

template<typename T>
int bar(T)
{ return 0; }

int i = bar(foo);  // which 'foo' ?

您可以通过将 abs 显式转换为您所指的函数的类型来告诉编译器:

std::transform(vec.begin(), vec.end(), vec.begin(), (int (*)(int))abs);

或者通过创建一个引用你想要的函数的变量:

int (*p)(int) = abs;
std::transform(vec.begin(), vec.end(), vec.begin(), p);

要将这两种转换合并为一个,您可以使用 lambda,如 Xeo 建议的那样,或使用 std::bind 例如

using std::placeholders::_1;
int (*p)(int) = abs;
std::transform(vec.begin(), vec.end(), vec.begin(),
               std::bind(p, std::bind(std::minus<int>(), dpi, _1)));

或者对于 C++03,您可以改用 boost::bind

【讨论】:

  • 精彩的答案。第二个问题如何:我想知道是否可以将以下两行代码合并为一个(即一个 std::transform 调用,具有相同的效果): std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus(), dpi)); std::transform(vec.begin(), vec.end(), vec.begin(), absd);
  • 正如我所说,请参阅 Xeo 的评论,或者我编辑了答案以显示如何使用bind
  • 嗨,我遇到了编译错误: using std::placeholders::_1; int (*p)(int) = abs; std::transform(vec.begin(), vec.end(), vec.begin(), std::bind(p, std::bind(std::minus(), dpi, _1)) );错误消息:1>D:\ProgramFiles\VS 2010\VC\include\xxcallfun(7): error C2664: 'int (int)' : cannot convert parameter 1 from 'std::tr1::_Bind_fty<_fty _bindn>' 到 'int'
猜你喜欢
  • 2019-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-14
  • 2016-03-23
  • 2014-01-19
  • 2021-06-20
相关资源
最近更新 更多