Что делать с типами имен шаблонов для необязательных аргументов? - PullRequest
2 голосов
/ 08 июля 2010

Прежде всего, код:

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 DataFile :: ForEachField (Func, Func2, bool)»: не удалось получить аргумент шаблона для «Func2», см. Объявление «DataFile :: ForEachField»

Можно ли как-то сделать второй параметр необязательным, при этом все еще используя шаблоны и не указывая вручную второй аргумент шаблона?

Ответы [ 4 ]

3 голосов
/ 08 июля 2010

Вы можете добавить перегрузку для ForEachField:

template<typename Func>
void ForEachField (Func normalHandler)
{
    ForEachField<Func, void *>(normalHandler, NULL, true);
}
1 голос
/ 08 июля 2010

Я знаю, что дублирование кода обычно рассматривается как «плохое», однако в этом случае я, вероятно, НЕ использовал бы проверку во время выполнения, чтобы определить, передал ли я аргумент ... всякий раз, когда проверка может быть выполнена во время компиляции...

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! к лямбде (что не работает)
0 голосов
/ 08 июля 2010

Как насчет того, чтобы сделать второй параметр нестандартным и создать перегруженный метод-обертку, который принимает один параметр typename Func.

0 голосов
/ 08 июля 2010

Поскольку вы уже используете функции C ++ 0x (лямбды), просто используйте другой: аргументы шаблона по умолчанию

template<typename Func, typename Func2 = void*>
void ForEachField(Func normalHandler, Func2 arrayHandler = NULL, bool skipUnknowns = true)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...