开发者

What to do with template typenames for optional arguments?

开发者 https://www.devze.com 2023-01-06 13:35 出处:网络
First of all, the code: template<typename Func, typename Func2> void ForEachField(Func normalHandler, Func2 arrayHandler = NULL, bool skipUnknow开发者_运维问答ns = true)

First of all, the code:

template<typename Func, typename Func2>
void ForEachField(Func normalHandler, Func2 arrayHandler = NULL, bool skipUnknow开发者_运维问答ns = 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);
    }
}

And an example of usage:

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

The second call doesn't work because it says:

OutputPhp.cpp(27): error C2783: 'void DataFile::ForEachField(Func,Func2,bool)' : could not deduce template argument for 'Func2' see declaration of 'DataFile::ForEachField'

Is there any way I can make the second parameter optional, while still using templates, and while not having to manually specify the second template argument?


You could add an overload for ForEachField:

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


I know that code duplication is usually regarded as "bad", however in this case I would probably NOT use a runtime check to detect whether or not I passed an argument... whenever the check can be done at compile time...

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

Remember that you can perfectly overload functions templates as usual.

This will in turn solve the two problems:

  • Second parameter is now optional (for all intents and purposes)
  • No more application of operator! on a lambda (which does not work)


Since you're using C++0x features already (lambdas), just use another one: default template arguments

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


What about making the second parameter non-default, and creating an overloaded wrapper method that takes a single typename Func parameter.

0

精彩评论

暂无评论...
验证码 换一张
取 消