How to sum variadic arguments passed in to a variadic macro?












9















I want a program that defines a macro that can count the number of arguments and pass them to a function sum which sums the arguments' values and returns the total. I managed to do it on GCC but I want to achieve it on Visual C++ 14.



#include "stdafx.h"
#include <iostream>
#include <cstdarg>


#define ELEVENTH_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
#define COUNT_ARGUMENTS(...) ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

#define SUM(...) sum(ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))


int sum(int n, ...) {

int sz{ n };
va_list ap;
va_start(ap, n);
int tmp{};
while (--sz)
tmp += va_arg(ap, int);

va_end(ap);

return tmp;
}

int main() {

std::cout << COUNT_ARGUMENTS(4,57,22,10,5,6,2,8,68,24,24,86,89,89,96,86) << std::endl; // 1
std::cout << SUM(5, 57, 4, 5) << std::endl; // 0
std::cout << COUNT_ARGUMENTS(5, 57, 10) << std::endl;// 1


std::cout << std::endl;
std::cin.get();
}


I don't know what's wrong with my code, it always gives me the sum is 0.










share|improve this question




















  • 3





    Shouldn't you forward the numbers passed to SUM to the function? And since this is C++, why not a variadic template?

    – tkausl
    Feb 1 at 20:53








  • 1





    Variadic macro has limited utility in C++ due to support for variadic templates. The question has more relevance in C, but an answer already exists.

    – jxh
    Feb 1 at 21:14











  • Possible duplicate of C++ preprocessor __VA_ARGS__ number of arguments

    – Mikel F
    Feb 1 at 21:47
















9















I want a program that defines a macro that can count the number of arguments and pass them to a function sum which sums the arguments' values and returns the total. I managed to do it on GCC but I want to achieve it on Visual C++ 14.



#include "stdafx.h"
#include <iostream>
#include <cstdarg>


#define ELEVENTH_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
#define COUNT_ARGUMENTS(...) ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

#define SUM(...) sum(ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))


int sum(int n, ...) {

int sz{ n };
va_list ap;
va_start(ap, n);
int tmp{};
while (--sz)
tmp += va_arg(ap, int);

va_end(ap);

return tmp;
}

int main() {

std::cout << COUNT_ARGUMENTS(4,57,22,10,5,6,2,8,68,24,24,86,89,89,96,86) << std::endl; // 1
std::cout << SUM(5, 57, 4, 5) << std::endl; // 0
std::cout << COUNT_ARGUMENTS(5, 57, 10) << std::endl;// 1


std::cout << std::endl;
std::cin.get();
}


I don't know what's wrong with my code, it always gives me the sum is 0.










share|improve this question




















  • 3





    Shouldn't you forward the numbers passed to SUM to the function? And since this is C++, why not a variadic template?

    – tkausl
    Feb 1 at 20:53








  • 1





    Variadic macro has limited utility in C++ due to support for variadic templates. The question has more relevance in C, but an answer already exists.

    – jxh
    Feb 1 at 21:14











  • Possible duplicate of C++ preprocessor __VA_ARGS__ number of arguments

    – Mikel F
    Feb 1 at 21:47














9












9








9


6






I want a program that defines a macro that can count the number of arguments and pass them to a function sum which sums the arguments' values and returns the total. I managed to do it on GCC but I want to achieve it on Visual C++ 14.



#include "stdafx.h"
#include <iostream>
#include <cstdarg>


#define ELEVENTH_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
#define COUNT_ARGUMENTS(...) ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

#define SUM(...) sum(ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))


int sum(int n, ...) {

int sz{ n };
va_list ap;
va_start(ap, n);
int tmp{};
while (--sz)
tmp += va_arg(ap, int);

va_end(ap);

return tmp;
}

int main() {

std::cout << COUNT_ARGUMENTS(4,57,22,10,5,6,2,8,68,24,24,86,89,89,96,86) << std::endl; // 1
std::cout << SUM(5, 57, 4, 5) << std::endl; // 0
std::cout << COUNT_ARGUMENTS(5, 57, 10) << std::endl;// 1


std::cout << std::endl;
std::cin.get();
}


I don't know what's wrong with my code, it always gives me the sum is 0.










share|improve this question
















I want a program that defines a macro that can count the number of arguments and pass them to a function sum which sums the arguments' values and returns the total. I managed to do it on GCC but I want to achieve it on Visual C++ 14.



#include "stdafx.h"
#include <iostream>
#include <cstdarg>


#define ELEVENTH_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
#define COUNT_ARGUMENTS(...) ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

#define SUM(...) sum(ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))


int sum(int n, ...) {

int sz{ n };
va_list ap;
va_start(ap, n);
int tmp{};
while (--sz)
tmp += va_arg(ap, int);

va_end(ap);

return tmp;
}

int main() {

std::cout << COUNT_ARGUMENTS(4,57,22,10,5,6,2,8,68,24,24,86,89,89,96,86) << std::endl; // 1
std::cout << SUM(5, 57, 4, 5) << std::endl; // 0
std::cout << COUNT_ARGUMENTS(5, 57, 10) << std::endl;// 1


std::cout << std::endl;
std::cin.get();
}


I don't know what's wrong with my code, it always gives me the sum is 0.







c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 1 at 21:24









NathanOliver

91.9k15129194




91.9k15129194










asked Feb 1 at 20:49









AdamMenzAdamMenz

794




794








  • 3





    Shouldn't you forward the numbers passed to SUM to the function? And since this is C++, why not a variadic template?

    – tkausl
    Feb 1 at 20:53








  • 1





    Variadic macro has limited utility in C++ due to support for variadic templates. The question has more relevance in C, but an answer already exists.

    – jxh
    Feb 1 at 21:14











  • Possible duplicate of C++ preprocessor __VA_ARGS__ number of arguments

    – Mikel F
    Feb 1 at 21:47














  • 3





    Shouldn't you forward the numbers passed to SUM to the function? And since this is C++, why not a variadic template?

    – tkausl
    Feb 1 at 20:53








  • 1





    Variadic macro has limited utility in C++ due to support for variadic templates. The question has more relevance in C, but an answer already exists.

    – jxh
    Feb 1 at 21:14











  • Possible duplicate of C++ preprocessor __VA_ARGS__ number of arguments

    – Mikel F
    Feb 1 at 21:47








3




3





Shouldn't you forward the numbers passed to SUM to the function? And since this is C++, why not a variadic template?

– tkausl
Feb 1 at 20:53







Shouldn't you forward the numbers passed to SUM to the function? And since this is C++, why not a variadic template?

– tkausl
Feb 1 at 20:53






1




1





Variadic macro has limited utility in C++ due to support for variadic templates. The question has more relevance in C, but an answer already exists.

– jxh
Feb 1 at 21:14





Variadic macro has limited utility in C++ due to support for variadic templates. The question has more relevance in C, but an answer already exists.

– jxh
Feb 1 at 21:14













Possible duplicate of C++ preprocessor __VA_ARGS__ number of arguments

– Mikel F
Feb 1 at 21:47





Possible duplicate of C++ preprocessor __VA_ARGS__ number of arguments

– Mikel F
Feb 1 at 21:47












2 Answers
2






active

oldest

votes


















11














Don't use a variadic macro. Visual C++ 14 (or 2015) is a C++11/14 compliant compiler. That means it it supports variadic templates. You can easily recurse a parameter pack to get the sum of the parameters and getting the count can be done by using sizeof.... This lets you write count as



template<typename... Args>
auto count(Args&&...)
{
return sizeof...(Args);
}


and then sum can be written as



// base case
template<typename T>
auto sum(T&& first)
{
return first;
}

// multiple parameters case
template<typename T, typename... Args>
auto sum(T&& first, Args&&... rest)
{
return first + sum(rest...);
}


using those in



int main()
{
std::cout << count(3,4,5) << "n";
std::cout << sum(3,4,5);
}


prints



3
12


which you can see in this live example.





As suggested by HolyBlackCat you can use the dummy array trick to avoid using recursion. That would give you a sum that looks like



template <typename ...P> 
auto sum(const P &... params)
{
using dummy_array = int;
std::common_type_t<P...> ret{}; // common_type_t is to find the appropriate type all of the parameter can be added to
(void)dummy_array{(void(ret += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
return ret;
}


Do note though that this might not work correctly for all types, like shown here with std::valarray. Changing it to



template <typename T, typename ...P> 
auto sum(T first, P&&... rest) // copy the first parameter to use it as the accumulator
{
using dummy_array = int;
(void)dummy_array{(void(first += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
return first;
}


should be more correct, although it could probably be improved some more (suggestions/edits welcomed)





If you can use a C++17 complaint compiler then sum can be even further simplified using a fold expression like



template<typename... Args>
auto sum(Args&&... rest)
{
return (rest + ...);
}





share|improve this answer


























  • As an alternative to recursion, I suggest the good ol' dummy array trick.

    – HolyBlackCat
    Feb 1 at 21:33






  • 1





    @HolyBlackCat Good suggestion. I've added it to the answer. I have noted though that it will fail as is if you are using std::valarray parameters.

    – NathanOliver
    Feb 1 at 21:42



















5














Adding onto @NathanOliver, if you'd like to use variadic templates without recursion, std::initializer_list and std::common_type are both available in C++11, allowing you to do this instead:



template <typename... Args,                                      
typename T = typename std::common_type<Args...>::type>
T sum(Args&&... args) {
std::initializer_list<T> l{args...};
return std::accumulate(l.begin(), l.end(), T{});
}


Edit: Note that this solution will allow sum to be invoked on all types that are implicitly convertible to a common type (that is what common_type does).



For example:



sum(1, 2, 3)    // Ok, all ints
sum(1, 2, true) // Ok, bool converts to int
sum(1, 2, 3.) // Error, int to double is a narrowing conversion





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54486962%2fhow-to-sum-variadic-arguments-passed-in-to-a-variadic-macro%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    11














    Don't use a variadic macro. Visual C++ 14 (or 2015) is a C++11/14 compliant compiler. That means it it supports variadic templates. You can easily recurse a parameter pack to get the sum of the parameters and getting the count can be done by using sizeof.... This lets you write count as



    template<typename... Args>
    auto count(Args&&...)
    {
    return sizeof...(Args);
    }


    and then sum can be written as



    // base case
    template<typename T>
    auto sum(T&& first)
    {
    return first;
    }

    // multiple parameters case
    template<typename T, typename... Args>
    auto sum(T&& first, Args&&... rest)
    {
    return first + sum(rest...);
    }


    using those in



    int main()
    {
    std::cout << count(3,4,5) << "n";
    std::cout << sum(3,4,5);
    }


    prints



    3
    12


    which you can see in this live example.





    As suggested by HolyBlackCat you can use the dummy array trick to avoid using recursion. That would give you a sum that looks like



    template <typename ...P> 
    auto sum(const P &... params)
    {
    using dummy_array = int;
    std::common_type_t<P...> ret{}; // common_type_t is to find the appropriate type all of the parameter can be added to
    (void)dummy_array{(void(ret += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return ret;
    }


    Do note though that this might not work correctly for all types, like shown here with std::valarray. Changing it to



    template <typename T, typename ...P> 
    auto sum(T first, P&&... rest) // copy the first parameter to use it as the accumulator
    {
    using dummy_array = int;
    (void)dummy_array{(void(first += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return first;
    }


    should be more correct, although it could probably be improved some more (suggestions/edits welcomed)





    If you can use a C++17 complaint compiler then sum can be even further simplified using a fold expression like



    template<typename... Args>
    auto sum(Args&&... rest)
    {
    return (rest + ...);
    }





    share|improve this answer


























    • As an alternative to recursion, I suggest the good ol' dummy array trick.

      – HolyBlackCat
      Feb 1 at 21:33






    • 1





      @HolyBlackCat Good suggestion. I've added it to the answer. I have noted though that it will fail as is if you are using std::valarray parameters.

      – NathanOliver
      Feb 1 at 21:42
















    11














    Don't use a variadic macro. Visual C++ 14 (or 2015) is a C++11/14 compliant compiler. That means it it supports variadic templates. You can easily recurse a parameter pack to get the sum of the parameters and getting the count can be done by using sizeof.... This lets you write count as



    template<typename... Args>
    auto count(Args&&...)
    {
    return sizeof...(Args);
    }


    and then sum can be written as



    // base case
    template<typename T>
    auto sum(T&& first)
    {
    return first;
    }

    // multiple parameters case
    template<typename T, typename... Args>
    auto sum(T&& first, Args&&... rest)
    {
    return first + sum(rest...);
    }


    using those in



    int main()
    {
    std::cout << count(3,4,5) << "n";
    std::cout << sum(3,4,5);
    }


    prints



    3
    12


    which you can see in this live example.





    As suggested by HolyBlackCat you can use the dummy array trick to avoid using recursion. That would give you a sum that looks like



    template <typename ...P> 
    auto sum(const P &... params)
    {
    using dummy_array = int;
    std::common_type_t<P...> ret{}; // common_type_t is to find the appropriate type all of the parameter can be added to
    (void)dummy_array{(void(ret += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return ret;
    }


    Do note though that this might not work correctly for all types, like shown here with std::valarray. Changing it to



    template <typename T, typename ...P> 
    auto sum(T first, P&&... rest) // copy the first parameter to use it as the accumulator
    {
    using dummy_array = int;
    (void)dummy_array{(void(first += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return first;
    }


    should be more correct, although it could probably be improved some more (suggestions/edits welcomed)





    If you can use a C++17 complaint compiler then sum can be even further simplified using a fold expression like



    template<typename... Args>
    auto sum(Args&&... rest)
    {
    return (rest + ...);
    }





    share|improve this answer


























    • As an alternative to recursion, I suggest the good ol' dummy array trick.

      – HolyBlackCat
      Feb 1 at 21:33






    • 1





      @HolyBlackCat Good suggestion. I've added it to the answer. I have noted though that it will fail as is if you are using std::valarray parameters.

      – NathanOliver
      Feb 1 at 21:42














    11












    11








    11







    Don't use a variadic macro. Visual C++ 14 (or 2015) is a C++11/14 compliant compiler. That means it it supports variadic templates. You can easily recurse a parameter pack to get the sum of the parameters and getting the count can be done by using sizeof.... This lets you write count as



    template<typename... Args>
    auto count(Args&&...)
    {
    return sizeof...(Args);
    }


    and then sum can be written as



    // base case
    template<typename T>
    auto sum(T&& first)
    {
    return first;
    }

    // multiple parameters case
    template<typename T, typename... Args>
    auto sum(T&& first, Args&&... rest)
    {
    return first + sum(rest...);
    }


    using those in



    int main()
    {
    std::cout << count(3,4,5) << "n";
    std::cout << sum(3,4,5);
    }


    prints



    3
    12


    which you can see in this live example.





    As suggested by HolyBlackCat you can use the dummy array trick to avoid using recursion. That would give you a sum that looks like



    template <typename ...P> 
    auto sum(const P &... params)
    {
    using dummy_array = int;
    std::common_type_t<P...> ret{}; // common_type_t is to find the appropriate type all of the parameter can be added to
    (void)dummy_array{(void(ret += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return ret;
    }


    Do note though that this might not work correctly for all types, like shown here with std::valarray. Changing it to



    template <typename T, typename ...P> 
    auto sum(T first, P&&... rest) // copy the first parameter to use it as the accumulator
    {
    using dummy_array = int;
    (void)dummy_array{(void(first += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return first;
    }


    should be more correct, although it could probably be improved some more (suggestions/edits welcomed)





    If you can use a C++17 complaint compiler then sum can be even further simplified using a fold expression like



    template<typename... Args>
    auto sum(Args&&... rest)
    {
    return (rest + ...);
    }





    share|improve this answer















    Don't use a variadic macro. Visual C++ 14 (or 2015) is a C++11/14 compliant compiler. That means it it supports variadic templates. You can easily recurse a parameter pack to get the sum of the parameters and getting the count can be done by using sizeof.... This lets you write count as



    template<typename... Args>
    auto count(Args&&...)
    {
    return sizeof...(Args);
    }


    and then sum can be written as



    // base case
    template<typename T>
    auto sum(T&& first)
    {
    return first;
    }

    // multiple parameters case
    template<typename T, typename... Args>
    auto sum(T&& first, Args&&... rest)
    {
    return first + sum(rest...);
    }


    using those in



    int main()
    {
    std::cout << count(3,4,5) << "n";
    std::cout << sum(3,4,5);
    }


    prints



    3
    12


    which you can see in this live example.





    As suggested by HolyBlackCat you can use the dummy array trick to avoid using recursion. That would give you a sum that looks like



    template <typename ...P> 
    auto sum(const P &... params)
    {
    using dummy_array = int;
    std::common_type_t<P...> ret{}; // common_type_t is to find the appropriate type all of the parameter can be added to
    (void)dummy_array{(void(ret += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return ret;
    }


    Do note though that this might not work correctly for all types, like shown here with std::valarray. Changing it to



    template <typename T, typename ...P> 
    auto sum(T first, P&&... rest) // copy the first parameter to use it as the accumulator
    {
    using dummy_array = int;
    (void)dummy_array{(void(first += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element
    return first;
    }


    should be more correct, although it could probably be improved some more (suggestions/edits welcomed)





    If you can use a C++17 complaint compiler then sum can be even further simplified using a fold expression like



    template<typename... Args>
    auto sum(Args&&... rest)
    {
    return (rest + ...);
    }






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 1 at 21:47

























    answered Feb 1 at 21:00









    NathanOliverNathanOliver

    91.9k15129194




    91.9k15129194













    • As an alternative to recursion, I suggest the good ol' dummy array trick.

      – HolyBlackCat
      Feb 1 at 21:33






    • 1





      @HolyBlackCat Good suggestion. I've added it to the answer. I have noted though that it will fail as is if you are using std::valarray parameters.

      – NathanOliver
      Feb 1 at 21:42



















    • As an alternative to recursion, I suggest the good ol' dummy array trick.

      – HolyBlackCat
      Feb 1 at 21:33






    • 1





      @HolyBlackCat Good suggestion. I've added it to the answer. I have noted though that it will fail as is if you are using std::valarray parameters.

      – NathanOliver
      Feb 1 at 21:42

















    As an alternative to recursion, I suggest the good ol' dummy array trick.

    – HolyBlackCat
    Feb 1 at 21:33





    As an alternative to recursion, I suggest the good ol' dummy array trick.

    – HolyBlackCat
    Feb 1 at 21:33




    1




    1





    @HolyBlackCat Good suggestion. I've added it to the answer. I have noted though that it will fail as is if you are using std::valarray parameters.

    – NathanOliver
    Feb 1 at 21:42





    @HolyBlackCat Good suggestion. I've added it to the answer. I have noted though that it will fail as is if you are using std::valarray parameters.

    – NathanOliver
    Feb 1 at 21:42













    5














    Adding onto @NathanOliver, if you'd like to use variadic templates without recursion, std::initializer_list and std::common_type are both available in C++11, allowing you to do this instead:



    template <typename... Args,                                      
    typename T = typename std::common_type<Args...>::type>
    T sum(Args&&... args) {
    std::initializer_list<T> l{args...};
    return std::accumulate(l.begin(), l.end(), T{});
    }


    Edit: Note that this solution will allow sum to be invoked on all types that are implicitly convertible to a common type (that is what common_type does).



    For example:



    sum(1, 2, 3)    // Ok, all ints
    sum(1, 2, true) // Ok, bool converts to int
    sum(1, 2, 3.) // Error, int to double is a narrowing conversion





    share|improve this answer






























      5














      Adding onto @NathanOliver, if you'd like to use variadic templates without recursion, std::initializer_list and std::common_type are both available in C++11, allowing you to do this instead:



      template <typename... Args,                                      
      typename T = typename std::common_type<Args...>::type>
      T sum(Args&&... args) {
      std::initializer_list<T> l{args...};
      return std::accumulate(l.begin(), l.end(), T{});
      }


      Edit: Note that this solution will allow sum to be invoked on all types that are implicitly convertible to a common type (that is what common_type does).



      For example:



      sum(1, 2, 3)    // Ok, all ints
      sum(1, 2, true) // Ok, bool converts to int
      sum(1, 2, 3.) // Error, int to double is a narrowing conversion





      share|improve this answer




























        5












        5








        5







        Adding onto @NathanOliver, if you'd like to use variadic templates without recursion, std::initializer_list and std::common_type are both available in C++11, allowing you to do this instead:



        template <typename... Args,                                      
        typename T = typename std::common_type<Args...>::type>
        T sum(Args&&... args) {
        std::initializer_list<T> l{args...};
        return std::accumulate(l.begin(), l.end(), T{});
        }


        Edit: Note that this solution will allow sum to be invoked on all types that are implicitly convertible to a common type (that is what common_type does).



        For example:



        sum(1, 2, 3)    // Ok, all ints
        sum(1, 2, true) // Ok, bool converts to int
        sum(1, 2, 3.) // Error, int to double is a narrowing conversion





        share|improve this answer















        Adding onto @NathanOliver, if you'd like to use variadic templates without recursion, std::initializer_list and std::common_type are both available in C++11, allowing you to do this instead:



        template <typename... Args,                                      
        typename T = typename std::common_type<Args...>::type>
        T sum(Args&&... args) {
        std::initializer_list<T> l{args...};
        return std::accumulate(l.begin(), l.end(), T{});
        }


        Edit: Note that this solution will allow sum to be invoked on all types that are implicitly convertible to a common type (that is what common_type does).



        For example:



        sum(1, 2, 3)    // Ok, all ints
        sum(1, 2, true) // Ok, bool converts to int
        sum(1, 2, 3.) // Error, int to double is a narrowing conversion






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Feb 1 at 21:51

























        answered Feb 1 at 21:38









        RichardRichard

        13317




        13317






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54486962%2fhow-to-sum-variadic-arguments-passed-in-to-a-variadic-macro%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            ComboBox Display Member on multiple fields

            Is it possible to collect Nectar points via Trainline?