具有默认值的C ++可变参数模板函数参数 [英] C++ variadic template function parameter with default value

查看:133
本文介绍了具有默认值的C ++可变参数模板函数参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,它带有一个带有默认值的参数。现在,我还希望它采用可变数量的参数并将其转发给其他函数。函数参数的默认值必须是最后一个,所以...我可以将该参数放在可变参数包之后,编译器将在调用函数时检测到是否在提供它吗?

I have a function which takes one parameter with a default value. Now I also want it to take a variable number of parameters and forward them to some other function. Function parameters with default value have to be last, so... can I put that parameter after the variadic pack and the compiler will detect whether I'm supplying it or not when calling the function?

(假定包中不包含最后一个参数的类型。如果有必要,我们可以假设,因为用户通常不知道该类型,否则将其视为错误用法还是我的界面...。)

(Assuming the pack doesn't contain the type of that one last parameter. If necessary, we can assume that, because that type is generally not supposed to be known to the user, otherwise it's considered as wrong usage of my interface anyway....)

template <class... Args>
void func (Args&&... args, SomeSpecialType num = fromNum(5))
{
}


推荐答案

不,包装必须是最后一个。

No, packs must be last.

但是您可以伪造它。您可以检测到包装中的最后一种类型。如果它是 SomeSpecialType ,则可以运行函数。如果不是 SomeSpecialType ,则可以递归调用自己,并转发参数并附加 fromNum(5)

But you can fake it. You can detect what the last type in a pack is. If it is SomeSpecialType, you can run your func. If it isn't SomeSpecialType, you can recursively call yourself with your arguments forwarded and fromNum(5) appended.

如果想花哨的话,可以使用SFINAE技术在编译时(即,不同的重载)进行此检查。但是,考虑到运行时检查在给定的过载下将保持不变,因此几乎可以肯定会对其进行优化,因此,SFINAE不应轻易使用。

If you want to be fancy, this check can be done at compile time (ie, a different overload) using SFINAE techniques. But that probably isn't worth the hassle, considering that the "run-time" check will be constant on a given overload, and hence will almost certainly be optimized out, and SFINAE shouldn't be used lightly.

这不会给您想要的签名,但是会给您想要的行为。您必须在注释中解释预期的签名。

This doesn't give you the signature you want, but it gives you the behavior you want. You'll have to explain the intended signature in comments.

在删除错字之类的东西后,类似这样的事情:

Something like this, after you remove typos and the like:

// extract the last type in a pack.  The last type in a pack with no elements is
// not a type:
template<typename... Ts>
struct last_type {};
template<typename T0>
struct last_type<T0> {
  typedef T0 type;
};
template<typename T0, typename T1, typename... Ts>
struct last_type<T0, T1, Ts...>:last_type<T1, Ts...> {};

// using aliases, because typename spam sucks:
template<typename Ts...>
using LastType = typename last_type<Ts...>::type;
template<bool b, typename T=void>
using EnableIf = typename std::enable_if<b, T>::type;
template<typename T>
using Decay = typename std::decay<T>::type;

// the case where the last argument is SomeSpecialType:
template<
  typename... Args,
  typename=EnableIf<
    std::is_same<
      Decay<LastType<Args...>>,
      SomeSpecialType
    >::value
  >
void func( Args&&... args ) {
  // code
}

// the case where there is no SomeSpecialType last:    
template<
  typename... Args,
  typename=EnableIf<
    !std::is_same<
      typename std::decay<LastType<Args...>>::type,
      SomeSpecialType
    >::value
  >
void func( Args&&... args ) {
  func( std::forward<Args>(args)..., std::move(static_cast<SomeSpecialType>(fromNum(5))) );
}

// the 0-arg case, because both of the above require that there be an actual
// last type:
void func() {
  func( std::move(static_cast<SomeSpecialType>(fromNum(5))) );
}

或类似的东西。

这篇关于具有默认值的C ++可变参数模板函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆