I am trying to write a function which accepts multiple arguments of different data types and return the sum of numbers. It should be able to decide what data type to be used for sum. For e.g.
if I write add(3,1,2,3) it should return sum as an int. However, if I write add(3,1,2.5,3.25) it should return sum as a double.
I tried using template, but giving compile time error. Here is the function
template <typename T>
T add(int n, ...)
{
T sum = 0;
va_list vl;
va_start(vl,n);
for(int i=0;i<n;i++)
{
sum += va_arg(vl,T);
}
va_end(vl);
return sum;
}
int main()
{
std::cout<<add(3,1,2,3);
return 0;
}
Compile Error: no matching function for call to 'add(int, int, int, int)'.
I think error is coming because I passed in va_arg T, but i don't know what else to pass to keep it generalised.
You should replace
std::cout<<add(3,1,2,3);
with
std::cout<<add<int>(3,1,2,3); // explicitly, int, double, float whatever
To make the code run succesfully as the compiler is unable to deduce the typename from implicit call.
Live code example here
Your function returns the value of type T, but you don't specify any argument of type T, making it impossible for compiler to deduce the type.
Other solution would be to add an overload that works for add(0) and pass first argument in add of type T. This can achieve OP's implicit deduction goal. Now compiler can deduce return type from first argument.
#include <cstdarg>
#include <iostream>
#include <cassert>
using namespace std;
int add(int n)
{
assert(0 == n);
return 0;
}
template <typename T>
T add(int n, T first, ...)
{
T sum = first;
va_list vl;
va_start(vl,first);
for(int i=1;i<n;i++)
{
sum += va_arg(vl,T);
}
va_end(vl);
return sum;
}
int main()
{
std::cout<<add(3,1,2,3);
std::cout<<add(3,1.5,2.,3.5);
return 0;
}
live code here
Why don't you use Varidaic Templates? – Mohit Jain
If you can write in C++14:
template<typename T>
inline T sum(T t){
return t;
}
template<typename T, typename... Ts>
inline auto sum(T t, Ts... ts){
return t+sum(ts...);
}
#include<iostream>
int main(){
std::cout<<sum(2.5, 2)<<'\n'
<<sum(2, 2.5)<<'\n'
<<sum(1u, 2.5, 3.f, '0')<<'\n';
}
If you write in C++11 under MSVC++ (it doesn't work under g++):
template<typename T>
inline T sum(T t){
return t;
}
template<typename T, typename... Ts>
inline auto sum(T t, Ts... ts)->decltype(t+sum(ts...)){
return t+sum(ts...);
}
#include<iostream>
int main(){
std::cout<<sum(2.5, 2)<<'\n' //works
<<sum(2, 2.5)<<'\n' //works
<<sum(1u, 2.5, 3.f, '0')<<'\n';//works under VC++, but not under g++
}
i think the problem is you determined the parameter type as int try to use
instead of: T Add (int n,...)
use: T Add( T n, ...)
Related
This is a good answer already, however, they passed arbitrary numbers of arguments as the parameters when I tried to do the same with arguments as typename (don't know the exact word) like this for example:
int sum=0;
int func()
{
return sum;
}
template <int first, int ... rest>
int func()
{
sum += first;
return func(rest...); //Error C2660 'func': function does not take 4 arguments
/*
return func<rest...>(); this also doesn't work: Error 'int func(void)': could not deduce template argument for 'first' and 'func': no matching overloaded function found
*/
}
int main()
{
cout << func<1,2,3,4,5>();
}
Why there's an error there? Are there any possible fixes? Also, I'm required to pass the argument as typenames, not parameters.
First of all, the "base" function also needs to be a template.
Then to differentiate the two templates, the parameter-pack template needs to take at least two template arguments.
And lastly, you can solve this without the global sum variable, but using the addition in the return statement.
Putting it all together:
template <int first>
int func()
{
return first;
}
template <int first, int second, int ...rest>
int func()
{
return first + func<second, rest...>();
}
For a simple use case as a sum of values, there are many ways (as in Some programmer dude and P Kramer answers).
I'll show you a variant of the recursive solution (Some programmer dude's answer) that isn't particular useful in this case but can come useful in other circumstances (avoiding code repetition when the ground function make something consistent and equal to the recursive version): instead of a ground case version that receive and manage the last value, a ground version that receive a defaulted type and do nothing (return zero, in the sum case):
template <typename = void>
int func ()
{ return 0; }
so you can write the recursive version as follows, without second
template <int first, int ... rest>
int func ()
{ return first + func<rest...>(); }
The trick is in the recursive call: func<rest...>()
When the ...rest template pack isn't empty, the recursive call func<rest...>() invoke the recursive func().
But when the ...rest template pack is empty, the recursive call func<rest...>() become func<>() that doesn't matches the recursive func() (at least a template integer value is required) but matches (thanks to the default void type) func<void>(), so the ground func() function.
If you want to return the sum of a parameter pack and you're okay with a slightly different syntax, you can use fold expressions from C++17 onward or build up recursion with 'if constexpr'
template<typename... args_t>
static constexpr auto sum(args_t&&... values)
{
return (values + ...);
}
// the sum is evaluated at compile time
static_assert(sum(1, 2, 3, 4) == 10ul);
// or like this without fold
template<int value, int... values>
constexpr int sum2()
{
if constexpr (sizeof...(values) > 0)
{
return value + sum2<values...>();
}
else
{
return value;
}
};
static_assert(sum2<1,2,3,4>() == 10);
Just for curiosity here is the version without recursion:
// C++11
template<typename... Ts>
void dummy(Ts... t)
{
}
template<typename T>
T addValue(T& sum, T value)
{
sum += value;
return 0;
}
template<typename SumType, typename... Ts>
SumType sumVariadicArgs(Ts... t)
{
SumType sum = 0;
dummy(addValue(sum, t)...);
return sum;
}
int main()
{
int sum = sumVariadicArgs<int>(1, 2, 3);
double sum2 = sumVariadicArgs<double>(1.0, 2.0, 3.0);
return 0;
}
I'm writing a plugin for software written in C++, here's a snippet where the plugin is defined:
extern "C"
irods::ms_table_entry* plugin_factory() {
// The number of msParam_t* arguments that it will accept
int numArguments = 2;
irods::ms_table_entry* msvc = new irods::ms_table_entry(numArguments);
msvc->add_operation(
"my_microservice",
std::function<int(msParam_t*, msParam_t*, ruleExecInfo_t*)>(MyMicroservice)
);
return msvc;
}
I'd like to be able to use numArguments to dynamically generate the std::function<int(msParam_t*, msParam_t*, ruleExecInfo_t*)> parameter pack. Where numArguments represents the number of msParam_t* arguments.
I'm not a C++ expert (especially with templating), so after some research I've found that this might be possible by implementing the following:
std::tuple
std::tuple_cat
std::index_sequence
std::make_integer_sequence
But I don't really know how to get started on implementing this. The examples I found were hard to understand, and I couldn't manage to translate them into my own needs. Can anyone provide tips, short examples, or references on how this might work? Any info is greatly appreciated!
I don't know if the following is exactly what you're asking but I think that what you want is being able to generate the right template parameters for the std::function based on the number of arguments that your MyMicroservice takes which is stored into the numParameters variable.
If that is the case you can simply omit writing them at all and use decltypeand let the compiler write them for you.
int myMicroservice1(int a,int b, int c){
return a+b+c;
}
int myMicroservice2(int a,int b, int c,int d){
return a*b*c-d;
}
int myMicroservice3(int a,int b, int c,int d,int e, int f){
return a*b*c+e+f;
}
template<typename... types_t>
void add_operation(const std::string & _op, std::function< int(types_t...)> _f ){
}
int main() {
add_operation("blabla",std::function<decltype(myMicroservice1)>(myMicroservice1));
add_operation("blabla",std::function<decltype(myMicroservice2)>(myMicroservice2));
add_operation("blabla",std::function<decltype(myMicroservice3)>(myMicroservice3));
return 0;
}
template<typename T>
struct toFunc;
template<typename...T>
struct toFunc<std::tuple<T...>>
{
using type = std::function<void(T...)>;
};
int main(int argc, char **argv) {
using t = std::tuple<int, int, int>;
using func = toFunc<t>::type;
auto f = func([](int a, int b, int c){std::cout << a << b << c << std::endl;});
f(1, 2, 3);
return 0;
}
toFunc typetrait will convert your tuple to a function type. not sure if you want that. If you want to call with the argument you maybe need to look for
http://en.cppreference.com/w/cpp/utility/apply
or you can use this implementation:
namespace detail
{
template <unsigned int N>
struct for_each_t_idx
{
template <template<std::size_t> class Functor, typename... ArgsT>
static void exec(const std::tuple<ArgsT...>& t, Functor<N> func)
{
for_each_t_idx<N - 1>::exec(t, func);
func<N - 1>(t);
}
};
template <>
struct for_each_t_idx<0>
{
template <template<std::size_t> class Functor, typename... ArgsT>
static void exec(const std::tuple<ArgsT...>& t, Functor<0> func)
{
}
};
}
template <template<std::size_t> class Functor, typename... ArgsT>
void for_each_idx(const std::tuple<ArgsT...>& t, Functor<sizeof...(ArgsT)> func)
{
detail::for_each_t_idx<sizeof...(ArgsT)>::exec(t, func);
}
This will call a given function for each element in a the tuple.
I try to pass to a variadic template function a list of references and pass it to another function. The code that I wrote is the following:
template <typename T>
void fun(cv::Point_<T> & pt) { pt.x++; pt.y++; }
template <class ... args>
void caller(args & ... list) {
typedef typename std::tuple_element<0, std::tuple<args...> >::type T;
std::array<std::reference_wrapper<T>, sizeof...(list)> values {list ... };
for(int i=0; i<values.size(); i++)
fun(values[i]);
}
then I call the function caller in this way:
cv::Point2f a, b, c;
caller(a, b, c);
the compiler give me the following error:
No matching function for call to 'fun'
Candidate template ignored: could not match 'Point_' against 'reference_wrapper'
what I missing?
Although std::reference_wrapper<T> has an implicit conversion to T&, you cannot use both an implicit conversion and template argument deduction at the same time, and template argument deduction is necessary to call fun.
Try
fun(values[i].get());
Even simpler is
template <typename...Args>
void caller(Args&...args)
{
auto tmp = { (func(args),0)..., 0 };
}
This uses the fact that parameter pack expansion can occur in braced init lists. Since func() returns void, we cannot simply use { func(args)... }, but use (func(args),0) to have an int. Finally, the last 0 is to ensure that the code compiles (and does nothing) in case of an empty parameter pack.
You can generalise this and write a template that calls a given generic function for every element of a pack:
template <typename Func, typename...Args>
void call_for_each(Func &&func, Args&&...args)
{
auto unused = { (func(std::forward<Args>(args)),0)...,0 };
}
which may be used like this (C++14)
int main()
{
int a=1;
double b=2.4;
auto func = [](auto&x) { std::cout<<' '<<x++; };
call_for_each(func,a,b);
std::cout<<'\n';
call_for_each(func,a,b);
std::cout<<'\n';
}
This uses a C++14 lambda (taking an auto argument). Note that the parameter pack must come last among the template parameters of call_for_each.
Since the goal of this might be to iterate over all args, here's a more generic solution. We are going to implement for_pack:
template<typename... Args, typename F>
void for_pack(F function, Args&&... args) {
using expand = int[];
(void)expand{(function(std::forward<Args>(args)), void(), 0)..., 0};
}
This will execute function for every args in Args.
Now, your function caller is much more trivial to implement:
template <typename... args>
void caller(args&... list) {
for_pack([&](cv::Point_<T>& arg){
fun(arg);
}, list...);
}
Since a google search for "c++ pass reference parameters to variadic template" gives this as first result, I'll put this generic solution here.
struct HH { /*...*/ void change_me() { /*...*/ } };
template<typename...T> void parms_r_refs() {}
template<typename H, typename...T> void parms_r_refs(H &h, T&...t) { h.change_me(); parms_r_refs(t...); }
template<typename...T> void parms_r_refs(T&...t) { parms_r_refs(t...); }
HH a, b, c;
..
parms_r_refs(a, b, c);
..
Here is an example case of what I'm trying to do (it is a "test" case just to illustrate the problem) :
#include <iostream>
#include <type_traits>
#include <ratio>
template<int Int, typename Type>
constexpr Type f(const Type x)
{
return Int*x;
}
template<class Ratio, typename Type,
class = typename std::enable_if<Ratio::den != 0>::type>
constexpr Type f(const Type x)
{
return (x*Ratio::num)/Ratio::den;
}
template</*An int OR a type*/ Something, typename Type>
constexpr Type g(const Type x)
{
return f<Something, Type>(x);
}
int main()
{
std::cout<<f<1>(42.)<<std::endl;
std::cout<<f<std::kilo>(42.)<<std::endl;
}
As you can see, there are two versions of the f() function : the first one takes an int as a template parameter, and the second one takes a std::ratio. The problem is the following :
I would like to "wrap" this function through g() which can take an int OR a std::ratio as first template parameter and call the good version of f().
How to do that without writing two g() functions ? In other words, what do I have to write instead of /*An int OR a type*/ ?
Here's how I would do it, but I've changed your interface slightly:
#include <iostream>
#include <type_traits>
#include <ratio>
template <typename Type>
constexpr
Type
f(int Int, Type x)
{
return Int*x;
}
template <std::intmax_t N, std::intmax_t D, typename Type>
constexpr
Type
f(std::ratio<N, D> r, Type x)
{
// Note use of r.num and r.den instead of N and D leads to
// less probability of overflow. For example if N == 8
// and D == 12, then r.num == 2 and r.den == 3 because
// ratio reduces the fraction to lowest terms.
return x*r.num/r.den;
}
template <class T, class U>
constexpr
typename std::remove_reference<U>::type
g(T&& t, U&& u)
{
return f(static_cast<T&&>(t), static_cast<U&&>(u));
}
int main()
{
constexpr auto h = g(1, 42.);
constexpr auto i = g(std::kilo(), 42.);
std::cout<< h << std::endl;
std::cout<< i << std::endl;
}
42
42000
Notes:
I've taken advantage of constexpr to not pass compile-time constants via template parameters (that's what constexpr is for).
g is now just a perfect forwarder. However I was unable to use std::forward because it isn't marked up with constexpr (arguably a defect in C++11). So I dropped down to use static_cast<T&&> instead. Perfect forwarding is a little bit overkill here. But it is a good idiom to be thoroughly familiar with.
How to do that without writing two g() functions ?
You don't. There is no way in C++ to take either a type or a value of some type, except through overloading.
It is not possible to have a template parameter taking both type and non-type values.
Solution 1:
Overloaded functions.
Solution 2:
You can store values in types. Ex:
template<int n>
struct store_int
{
static const int num = n;
static const int den = 1;
};
template<class Ratio, typename Type,
class = typename std::enable_if<Ratio::den != 0>::type>
constexpr Type f(const Type x)
{
return (x*Ratio::num)/Ratio::den;
}
template<typename Something, typename Type>
constexpr Type g(const Type x)
{
return f<Something, Type>(x);
}
But with this solution you will have to specify g<store_int<42> >(...) instead of g<42>(...)
If the function is small, I advise you to use overloading.
I need to pass a function to an operator. Any unary function having correct arg type. Return type can be anything. Because this is library code, I can not wrap it or cast f to specific overload (outside of operator*). Function takes operator* 1st arg as it own argument. Artificial example below compiles and returns correct results. But it has hardcoded int return type—to make this example compile.
#include <tuple>
#include <iostream>
using namespace std;
template<typename T>
int operator* (T x, int& (*f)(T&) ) {
return (*f)(x);
};
int main() {
tuple<int,int> tpl(42,43);
cout << tpl * get<0>;
}
Is it possible to make operator* to accept f with arbitrary return type?
UPDATE - GCC bug?
Code:
#include <tuple>
template<typename T, typename U>
U operator* (T x, U& (*f)(T&) ) {
return (*f)(x);
};
int main() {
std::tuple<int,int> tpl(42,43);
return tpl * std::get<0,int,int>;
}
Compiles and runs correctly with gcc462 and 453 but is reject with gcc471 and 480. So it is possible GCC regression bug. I've submitted bug report:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54111
EDIT
I've changed example to use tuple as arg - it was possible trivially deduce return type in previous example.
EDIT2
Many people could not understand what is needed, so I've changed call function to operator* to make example more real.
Yes, if this is what you mean:
template<typename T, typename F>
auto call (T x, F f) -> decltype(f(x)) {
return (f)(x);
}
There are actually a lot of ways to do that.
As an answer to your updated question:
as discussed by #DavidRodríguez, get<0> is not enough, nor the syntatically correct &get<0>. What you need is &get<0,int,int>. Follows your example, it would be:
#include <tuple>
using namespace std;
template<typename T, typename U>
U call (T x, U (*f)(T&) ) {
return (*f)(x);
};
int main() {
tuple<int,int> tpl(42,43);
call(tpl, &get<0,int,int>);
return 0;
}
During normal use of std::get<>(), the int,int part is deduced automatically. But in your situation you need to provide it, since there is no parameters. One workaround is a custom get template function:
#include <tuple>
using namespace std;
template <size_t I, typename T>
auto myGet(T& tpl) -> decltype(get<I>(tpl))
{
return get<I>(tpl);
}
template<typename T, typename U>
U call (T x, U (*f)(T&) ) {
return (*f)(x);
};
int main() {
tuple<int,int> tpl(42,43);
auto get0 = &myGet<0, decltype(tpl)>;
call(tpl, get0);
// call(tpl, &myGet<0, decltype(tpl)>); // all in one line, do not work
return 0;
}
You should be able to do this:
template<typename T,typename U>
U call (T x, U (*f)(T) ) {
return (*f)(x);
};