代码之家  ›  专栏  ›  技术社区  ›  Andreas Bonini

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

  •  2
  • Andreas Bonini  · 技术社区  · 15 年前

    首先,代码:

    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:“void” 数据文件::foreachfield(func,func2,bool)' :无法推导模板参数 关于“函数2” 请参见“datafile::foreachfield”的声明

    有没有任何方法可以使第二个参数成为可选的,同时仍然使用模板,而不必手动指定第二个模板参数?

    4 回复  |  直到 15 年前
        1
  •  3
  •   Andreas Bonini    15 年前

    您可以为添加重载 ForEachField :

    template<typename Func>
    void ForEachField (Func normalHandler)
    {
        ForEachField<Func, void *>(normalHandler, NULL, true);
    }
    
        2
  •  1
  •   Matthieu M.    15 年前

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

    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); }
        }
    }
    

    请记住,您可以像往常一样完全重载函数模板。

    这将依次解决两个问题:

    • 第二个参数现在是可选的(用于所有目的和目的)
    • 不再应用 operator! 在lambda上(不起作用)
        3
  •  0
  •   Tyler McHenry    15 年前

    既然您已经使用了C++ 0x特性(lambdas),只需使用另一个:默认模板参数

    template<typename Func, typename Func2 = void*>
    void ForEachField(Func normalHandler, Func2 arrayHandler = NULL, bool skipUnknowns = true)
    
        4
  •  0
  •   Mark B    15 年前

    将第二个参数设为非默认参数,并创建一个重载的包装方法 typename Func 参数。