如何处理可选参数的模板类型名称?

时间:2010-07-07 20:28:34

标签: c++ templates lambda c++11

首先,代码:

template<typename Func, typename Func2>
void ForEachField(Func normalHandler, Func2 arrayHandler = NULL, bool skipUnknowns = true)
{
    for(int i = 0; i < mFields.size(); ++i)
    {
        Field *f = mFields[i];

        if(skipUnknowns && f->IsUnknown())
            continue;

        if(f->GetCount() == 1 || !arrayHandler)
            normalHandler(f);
        else
            arrayHandler(f);
    }
}

使用示例:

df->ForEachField(
    [&](Field *field) { f << "\t" << format("public $%s;\n") % field->GetName(); },
    [&](Field *field) { f << "\t" << format("public $%s;\n") % field->GetName() % field->GetSize(); }
); // Works

df->ForEachField(
    [&](Field *field) { WriteLine(f, format("\t\t'%s' => array('type' => '%s'),") % field->GetName() % field->GetTypeInfo()->Name);
}); // Doesn't work

第二个电话不起作用,因为它说:

  

OutputPhp.cpp(27):错误C2783:'无效   数据文件:: ForEachField(FUNC键FUNC2,布尔)”   :无法推断出模板参数   为'Func2'             请参阅'DataFile :: ForEachField'的声明

有没有办法让第二个参数可选,同时仍然使用模板,而不必手动指定第二个模板参数?

4 个答案:

答案 0 :(得分:3)

您可以为ForEachField添加重载:

template<typename Func>
void ForEachField (Func normalHandler)
{
    ForEachField<Func, void *>(normalHandler, NULL, true);
}

答案 1 :(得分:1)

我知道代码重复通常被视为“坏”,但是在这种情况下,我可能不会使用运行时检查来检测我是否传递了参数...每当检查可以在编译时完成。 ..

template<typename Func, typename Func2>
void ForEachField(Func normalHandler, Func2 arrayHandler, bool skipUnknowns = true)
{
    for(int i = 0; i < mFields.size(); ++i)
    {
        Field *f = mFields[i];

        if(skipUnknowns && f->IsUnknown()) { continue; }

        if(f->GetCount() == 1) { normalHandler(f); }
        else { arrayHandler(f); }
    }
}


template<typename Func>
void ForEachField(Func normalHandler, bool skipUnknowns = true)
{
    for(int i = 0; i < mFields.size(); ++i)
    {
        Field *f = mFields[i];

        if(skipUnknowns && f->IsUnknown()) { continue; }

        if(f->GetCount() == 1) { normalHandler(f); }
    }
}

请记住,您可以像往常一样完美地重载功能模板。

这将反过来解决两个问题:

  • 第二个参数现在是可选的(出于所有意图和目的)
  • {lambisda上没有operator!的应用(不起作用)

答案 2 :(得分:0)

由于您已经使用了C ++ 0x功能(lambdas),只需使用另一个:默认模板参数

template<typename Func, typename Func2 = void*>
void ForEachField(Func normalHandler, Func2 arrayHandler = NULL, bool skipUnknowns = true)

答案 3 :(得分:0)

如何使第二个参数成为非默认值,并创建一个带有单个typename Func参数的重载包装器方法。