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.
精彩评论