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

发布于 2024-09-08 17:20:10 字数 1222 浏览 3 评论 0原文

首先,代码:

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)' : 无法推断出模板参数 对于“功能2” 请参阅“DataFile::ForEachField”的声明

有什么方法可以使第二个参数可选,同时仍然使用模板,并且不必手动指定第二个模板参数?

First of all, the code:

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情域 2024-09-15 17:20:10

您可以为 ForEachField 添加重载:

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

You could add an overload for ForEachField:

template<typename Func>
void ForEachField (Func normalHandler)
{
    ForEachField<Func, void *>(normalHandler, NULL, true);
}
苄①跕圉湢 2024-09-15 17:20:10

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

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

记住您可以像往常一样完美地重载函数模板。

这将依次解决两个问题:

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

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)
遮了一弯 2024-09-15 17:20:10

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

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

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)
梦里的微风 2024-09-15 17:20:10

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文