变长参数

参数个数类型不确定的函数,

c语言例子如下

Technically to use variable number of arguments in C you include stdarg.h. From that you'll get the va_list type as well as three functions that operate on it called va_start(), va_arg() and va_end().

/*c语言的variadic function*/
#include<stdarg.h>

int maxof(int n_args, ...)
{
    va_list ap;
    va_start(ap, n_args);
    int max = va_arg(ap, int);
    for(int i = 2; i <= n_args; i++) {
        int a = va_arg(ap, int);
        if(a > max) max = a;
    }
    va_end(ap);
    return max;
}

c++

// myPrintf.cpp

#include <iostream>
 
void myPrintf(const char* format){                           // (3)
    std::cout << format;
}
 
template<typename T, typename ... Args>
void myPrintf(const char* format, T value, Args ... args){   // (4)
    for ( ; *format != '\0'; format++ ) {                    // (5)
        if ( *format == '%' ) {                              // (6) 
           std::cout << value;
           myPrintf(format + 1, args ... );                  // (7)
           return;
        }
        std::cout << *format;                                // (8)
    }
}
 
int main(){    
    myPrintf("\n");                                          // (1)    
    myPrintf("% world% %\n", "Hello", '!', 2011);            // (2)    
    myPrintf("\n");                                             
}

std::unique

template <typename T, typename ... Args>
std::unique_ptr<T> make_unique(Args&& ... args){
    return std::unique_ptr<T>(new T(std::forward<Args>(args) ... ));
}

Fold Expressions

Fold Expressions 之前

//如果没有这个单参的重载,递归没办法结束
template<typename T>
T add(const T& arg)
{
  return arg;
}

template<typename T, typename... ARGS>
T add(const T& arg, const ARGS&... args)
{
  return arg + add(args...);
}

int main()
{
  return add(1, 2u, 3u);
}

//有了Fold Expressions之后

template<typename... ARGS>
auto add(const ARGS&... args)
{
  return (args + ...);
}

int main()
{
  return add(1, 2u, 3u);
}

结论

variadic function 类型不安全,编译不报错,出很多运行时错误。所以能不用就不用。不过如果比较关心二进制文件的大小,或者指令缓存很敏感,那么可以用c-style variadic function( C-style variadic functions produce less code when compiled than C++-style variadic templates, so if you're concerned about binary size or instruction cache pressure, you should consider implementing your functionality with varargs instead of as a template.)
在c++编程中,保留c-stype variadic function的唯一原因就是向后兼容。需要用到变长参数时,c++的选择应该是variadic template。

附录

c-style的变长参数函数还有个用处,如下所示:
(It is remarkably convenient that in C++ variadic functions can have no regular parameters. Also a variadic function is the least fit candidate within overload resolution (if a function call has at least one argument). Like any other function a variadic one can be only declared but never called:)

template <class T>
struct HasFoo
{
private:
    template <class U, class = decltype(std::declval<U>().foo())>
    static void detect(const U&);

    static int detect(...);

public:
    static constexpr bool value = 
    std::is_same<void, decltype(detect(std::declval<T>()))>::value;
};

c++14,可以写成下面这样,更容易理解一些

template <class T>
struct HasFoo
{
private:
    template <class U, class = decltype(std::declval<U>().foo())>
    static constexpr bool detect(const U*)
    {
        return true;
    }

    template <class U>
    static constexpr bool detect(...){
        return false;
    }

public:
    static constexpr bool value = detect<T>(nullptr);
};
posted on 2020-02-20 21:51  ConfuciusPei  阅读(96)  评论(0编辑  收藏  举报