【问题标题】:C++ STL 101: Overload function causes build errorC++ STL 101:重载函数导致构建错误
【发布时间】:2010-04-30 16:08:42
【问题描述】:

如果我不重载 myfunc,则可以工作的简单代码。

void myfunc(int i)
{
    std::cout << "calling myfunc with arg " << i << std::endl;
}
void myfunc(std::string s)
{
    std::cout << "calling myfunc with arg " << s << std::endl;
}
void testalgos()
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);

    std::vector<std::string> s;
    s.push_back("one");
    s.push_back("two");

    std::for_each( v.begin(), v.end(), myfunc);
    std::for_each( s.begin(), s.end(), myfunc);
    return;
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::cout << "Hello World" << std::endl;
    testalgos();
    return 0;
}

两个 for_each 调用都会重复以下构建错误。

错误 C2914: 'std::for_each' : 无法推断模板参数,因为函数参数不明确 错误 C2784:“_Fn1 std::for_each(_InIt,_InIt,_Fn1)”:无法从“std::_Vector_iterator<_ty>”推导出“_InIt”的模板参数。

如果我不重载 myfunc,它确实有效。有人可以解释这里发生了什么。

TIA

【问题讨论】:

  • 看起来你的代码标签倒退了。你能解决吗?
  • 编译器告诉你参数不明确。您是否希望编译器为您选择其中之一?好问题是“我怎样才能消除这个电话的歧义?”。

标签: c++ stl


【解决方案1】:

在这种情况下,编译器无法解析重载。 std::for_each() 期望某个任意类型的 F 为其函子,而不是某些特定的函数类型,因此重载的 myFunc 在这里是模棱两可的。

您可以明确选择要使用的重载:

std::for_each( v.begin(), v.end(), (void (*)(int))myfunc);
std::for_each( s.begin(), s.end(), (void (*)(std::string))myfunc);

替代品(后两个来自cmets)

typedef void (*IntFunc)(int);
std::for_each(/*...*/, (IntFunc)myfunc);

typedef void IntFunc(int);
std::for_each(/*...*/, static_cast<IntFunc*>(&myFunc));

// using identity (e.g. from boost or C++0x):
std::for_each(/*...*/, (identity<void(int)>::type*)myfunc);

【讨论】:

  • 谢谢。因此,编译器确实无法解析,我们需要添加“提示”。只是好奇,我是否在所有 STL 或模板相关代码中都需要这个?
  • 这取决于你调用的模板函数——如果可以解决重载,你就不需要它,例如template&lt;class T&gt; void f(T, void (*)(T)) 可以与 f(someInt, myFunc) 配合使用。然而,STL 大多使用完全无限制的函数参数类型,并且需要 "hints"
  • typedef 也可以在没有括号的情况下工作,显式编写 * 和 C++ 风格的强制转换:typedef void IntFunc(int); std::for_each( ..., static_cast&lt;IntFunc *&gt;( &amp;myFunc ) );
  • ... 或使用身份时std::for_each(..., (identity&lt;void(int)&gt;::type*)myfunc); :)
【解决方案2】:

编译器无法推断函子的类型。你可以制作你的函数模板:

template<typename T> void myfunc(T);

template<> void myfunc(int i)
{
    std::cout << "calling myfunc with arg " << i << std::endl;
}
template<> void myfunc(std::string s)
{
    std::cout << "calling myfunc with arg " << s << std::endl;
}

然后按如下方式使用:

std::for_each( v.begin(), v.end(), myfunc<int>);
std::for_each( s.begin(), s.end(), myfunc<std::string>);

【讨论】:

  • 我想我正在寻找这样的东西。谢谢。回到我的教程。
  • 如果不需要模板,大多数人期望纯重载。请参阅 gotw.ca/publications/mill17.htm 了解警告。
【解决方案3】:

编译器无法推断出要使用哪个,因为两个重载都会同样匹配参数(不依赖于迭代器的类型)。

除了将参数显式转换为合适的指针类型之外,另一种选择可能是使用std::ptr_fun 辅助函数将其包装在函子中,并通过显式给出(部分)它来帮助模板推导。

std::for_each( v.begin(), v.end(), std::ptr_fun<int>(myfunc));
std::for_each( s.begin(), s.end(), std::ptr_fun<std::string>(myfunc));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-20
    • 2011-09-14
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    相关资源
    最近更新 更多