How can I use va_arg in a loop without knowing how many optional arguments there are in C++?

Ope*_*tor 1 c++ templates variadic-functions variadic-templates

I want to write a function which takes at least two integer and returns the sum of all integer passed to the function:

int sumOfAtLeastTwoIntegers(int a, int b, ...){
   
    int sum = a+b;
    va_list ptr;
    va_start(ptr,b);
    for(){
        sum += va_arg(ptr, int)
    }

    va_end(ptr);
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

I want to know how the expression in the for loop has to look like such that the loop continues until all optional arguments were added to the sum. How would I achieve this without knowing how many optional arguments were passed to the function? The function call would look like this:

sumOfAtLeastTwoIntegers(2,3,4,5,1,0,200);
Run Code Online (Sandbox Code Playgroud)

pax*_*blo 9

There are generally two ways to handle variable arguments, pre-knowledge and post-knowledge.

Pre-knowledge is like with printf("%d %c\n", anInt, aChar), there's an argument up front which you can use to figure out how many remain. An example of that would be:

int sumOfInts(size_t count, int a, ...); // Needs "count" integers.
int eleven = sumOfInts(2, 4, 7);
Run Code Online (Sandbox Code Playgroud)

Post-knowledge requires you to have a sentinel value that tells you when to stop, such as with:

int sumOfNonZeroInts(int a, ...); // Needs non-zero integers, stops at 0.
int eleven = sumOfInts(4, 7, 0);
Run Code Online (Sandbox Code Playgroud)

One other thing you may want to consider is steering clear of variable argument lists, there are much more expressive ways in C++ for doing what you want with, for example, vectors. The following provides one way of doing this:

#include <iostream>
#include <vector>

template<typename T> T sumOf(const std::vector<T> &vec) {
    T acc = T();
    for (const T &item: vec)
        acc += item;
    return acc;
}

int main() {
    auto eleven = sumOf<int>({4, 7}); 
    std::cout << "Four plus seven is equal to " << eleven << '\n';
}
Run Code Online (Sandbox Code Playgroud)

This isn't necessarily as fast as variable arguments, but my default position nowadays is to generally optimise for readability first :-)


asm*_*mmo 5

我建议使用如下所示的可变参数模板。只有当你至少给它两个整数时它才有效。而且所有的 args 也必须是整数。

#include<iostream>
#include <type_traits>

template< typename ... Args>
std::enable_if_t<std::is_same_v<std::common_type_t<Args...>, int>, int>
sum(int arg1, Args...args)
{
    return (args+...+arg1);
}
int main(){

    std::cout << sum(1,2);//working
    std::cout << sum(1,.2);//compile error
    std::cout << sum(1);//compile error
 
}
Run Code Online (Sandbox Code Playgroud)