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

C++ 如何处理可选参数的模板类型名?,c++,templates,lambda,c++11,C++,Templates,Lambda,C++11,首先,守则: 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(skipUnkn

首先,守则:

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);
    }
}
模板
void ForEachField(Func normalHandler,Func2 arrayHandler=NULL,bool skipUnknowns=true)
{
对于(int i=0;iIsUnknown())
继续;
如果(f->GetCount()==1 | |!arrayHandler)
(f);
其他的
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
df->ForEachField(
[&](字段*字段){f ForEachField(
[&](字段*字段){WriteLine(f,格式(“\t\t'%s'=>array('type'=>'%s'),”)%Field->GetName()%Field->GetTypeInfo()->Name);
});//不起作用
第二个电话不起作用,因为它说:

OutputPhp.cpp(27):错误C2783:'无效 数据文件::ForEachField(Func,Func2,bool)' :无法推断模板参数 对于“Func2” 请参阅“DataFile::ForEachField”的声明


在仍然使用模板并且不必手动指定第二个模板参数的情况下,有什么方法可以使第二个参数成为可选的吗?

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

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

您可以为
ForEachField
添加重载:

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

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

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

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); }
    }
}
模板
void ForEachField(Func normalHandler,Func2 arrayHandler,bool skipUnknowns=true)
{
对于(int i=0;iIsUnknown()){continue;}
如果(f->GetCount()==1){normalHandler(f);}
else{arrayHandler(f);}
}
}
模板
void ForEachField(Func normalHandler,bool skipUnknowns=true)
{
对于(int i=0;iIsUnknown()){continue;}
如果(f->GetCount()==1){normalHandler(f);}
}
}
请记住,您可以像往常一样完全重载函数模板

这将反过来解决两个问题:

  • 第二个参数现在是可选的(用于所有目的)
  • 不再在lambda上应用
    操作符!
    (不起作用)

它似乎不起作用:
错误C4519:只允许在类模板上使用默认模板参数
必须是g++和MSVC++之间的差异。它在g++上工作。是的,MSVC还不支持这一点。(由于两个编译器都不支持C++0x的主要部分,所以说“只使用另一个C++0x功能”有点乐观):)这实际上是个好主意。显然它应该是
ForEachField
,否则我会遇到同样的问题;)但现在我遇到了另一个问题..!如果arrayHandler是一个lambda,arrayHandler不起作用,现在试图找到一个解决方案:哦,原来的版本确实编译了,尽管我没有运行它。