由 lambda 函数的 return 值定义的模板
Tempate defined by return value of lambda function
让它成为具有此类行为要求的模板:
template<typename MyActionLambda>
void enumerateChildrenByTag(QDomNodeList& list, const QString& tag, MyActionLambda action )
{
for(int i = 0; i < list.size(); i++) {
QDomElement el = list.item(i).firstChildElement(tag);
while(!el.isNull())
{
if( typeid(decltype(action(el))) == typeid(SomeType) )
{
auto res = action(el)
// do something with res
}
else
// do something with action(el)
el = el.nextSiblingElement(tag);
}
}
}
这显然是不可能的,因为 lambda 的编写方式具有 void return 类型,因为 if() 的两个分支都应该是合法的。除了将 declspec 作为模板参数的默认值并专门化两个模板之外,是否有更简单的方法来解决此问题?
使用 C++17,您可以编写
if constexpr( std::is_same<decltype(action(el)),SomeType>::value )
auto res = action(el);
else
{ /* do something else */ }
但我认为这种构造使用模板函数更具可读性,您可以专门针对 SomeType
:
template<class X>
void someFunction(const X& x) { /* standard case */ }
template<>
void someFunction(const SomeType& x) { /* SomeType case */ }
在你的循环中你只需调用:
for(QDomElement el = list.item(i).firstChildElement(tag);
!el.isNull(); el = el.nextSiblingElement(tag))
someFunction(action(el));
让它成为具有此类行为要求的模板:
template<typename MyActionLambda>
void enumerateChildrenByTag(QDomNodeList& list, const QString& tag, MyActionLambda action )
{
for(int i = 0; i < list.size(); i++) {
QDomElement el = list.item(i).firstChildElement(tag);
while(!el.isNull())
{
if( typeid(decltype(action(el))) == typeid(SomeType) )
{
auto res = action(el)
// do something with res
}
else
// do something with action(el)
el = el.nextSiblingElement(tag);
}
}
}
这显然是不可能的,因为 lambda 的编写方式具有 void return 类型,因为 if() 的两个分支都应该是合法的。除了将 declspec 作为模板参数的默认值并专门化两个模板之外,是否有更简单的方法来解决此问题?
使用 C++17,您可以编写
if constexpr( std::is_same<decltype(action(el)),SomeType>::value )
auto res = action(el);
else
{ /* do something else */ }
但我认为这种构造使用模板函数更具可读性,您可以专门针对 SomeType
:
template<class X>
void someFunction(const X& x) { /* standard case */ }
template<>
void someFunction(const SomeType& x) { /* SomeType case */ }
在你的循环中你只需调用:
for(QDomElement el = list.item(i).firstChildElement(tag);
!el.isNull(); el = el.nextSiblingElement(tag))
someFunction(action(el));