I have refered this link to meet my requirement .
But when I am trying to implement the same in my code, it is throwing an error.
template<typename T, typename... Args>
void fun(T t, Args... args)
{
cout << t;
}
int main()
{
fun(1, 2.0, "Ranjan", "hi");//Error happens here
return 0;
}
The error at fun() is template<class T, <error type>>
What is going wrong here?
VS2010 does not support variadic templates. See C++11 Features. VS2012 does not support it either, according to that page, so upgrading is not a solution at the moment.
Search for c++03 mimic variadic templates to determine if there is an alternative (one example from this site: How to implement "Variadic Template" with pre-c++0x(VS2008)?).
The problem is that you are using only the first, and not other template arguments. The g++ warning clearly explains it.
This example uses all arguments, and add a function for no arguments :
#include <iostream>
void fun()
{
std::cout<<std::endl;
}
template<typename T, typename... Args>
void fun(T t, Args... args)
{
std::cout << t;
fun(args...);
}
int main()
{
fun(1, 2.0, "Ranjan", "hi");//Error happens here
}
Related
I think code will better illustrate my need:
template <typename F>
struct return_type
{
typedef ??? type;
};
so that:
return_type<int(*)()>::type -> int
return_type<void(*)(int,int)>::type -> void
I know of decltype and result_of but they need to have arguments passed. I want to deduce the return type of a function pointer from a single template parameter. I cannot add the return type as a parameter, because that's exactly what I want to hide here...
I know there's a solution in boost, but I can't use it, and an attempt to dig it out from boost resulted in a spectacular failure (as it often does).
C++11 solutions welcome (as long as supported in VS2012).
If you can use variadic templates (November '12 CTP), this should work:
template <class F>
struct return_type;
template <class R, class... A>
struct return_type<R (*)(A...)>
{
typedef R type;
};
Live example.
If you can't use variadic templates, you'll have to provide specific specialisations for 0, 1, 2, ... parameters (by hand or preprocessor-generated).
EDIT
As pointed out in the comments, if you want to work with variadic functions as well, you'll have to add one extra partial specialisation (or one for each parameter count in the no-variadic-templates case):
template <class R, class... A>
struct return_type<R (*)(A..., ...)>
{
typedef R type;
};
It has been a while since the question has been asked. For C++17, there is an interesting option. However, the syntax is a bit different from what was originally asked, but the result (a type) is the same.
First, we need a helper function. As you see here, the function accepts a function pointer and returns an object of type R. We need this only for a decltype statement and therefore this function will never be called, so a forward declaration is sufficient.
template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...)); // forward declaration only for decltype
The trick is to provide the function pointer as a template auto parameter, which is forwarded to a decltype statement:
template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));
Now it is easy to get the return type:
#include <iostream>
#include <type_traits>
template<typename R, typename... ARGS>
static R return_type(R (*)(ARGS...)); // forward declaration only for decltype
template<auto FUNCTION_POINTER>
using ReturnType = decltype(return_type(FUNCTION_POINTER));
int func1(char c, int i, long l); // also here only forward declarations needed
void func2(unsigned u, float f);
double func3(bool b);
int main()
{
std::cout << std::is_same_v<int, ReturnType<func1>> << std::endl;
std::cout << std::is_same_v<void, ReturnType<func2>> << std::endl;
std::cout << std::is_same_v<double, ReturnType<func3>> << std::endl;
std::cout << std::is_same_v<void, ReturnType<func1>> << std::endl;
}
You can try the complete example in Wandbox: https://wandbox.org/permlink/5akL0MQDoDuJlQNY
#include <iostream>
template<typename T>
class A
{
};
template <typename T, typename T2, typename...Ts, typename = void >
//^remove this compiles
void func(T &&expr, T2 &&case1, Ts &&... args)
{
std::cout << "General\n";
}
template <typename T, typename A_Type, typename...Ts, typename = void>
//^remove this compiles
auto func(T &&expr, A<A_Type>&&, Ts &&... args)
{
std::cout << "A<Type>\n";
}
int main()
{
func(1, A<int>{}, 2); //ambiguous call
}
GCC 10.1 and older gives a ambiguous call error, but it compiles with 10.2. Demo here. I wonder if it's a bug on older version of GCC or my code is wrong and shouldn't compile.
The anonymous typename is for some SFINAE stuff, and I want a workaround to make it compile on older version of GCC.
GCC Bug 96976 (Resolved; implemented in GCC 10.2, GCC 11)
This looks like GCC resolved bug
Bug 96976 - g++ reports "call of overloaded '...' is ambiguous" when universal reference is used
which was recently marked as resolved
Jonathan Wakely 2020-09-08 11:56:59 UTC
Fixed on trunk by r11-1571
It's also fixed on the gcc-10 branch by r10-8343
where the solution has been implemented for GCC 10.2 and 11.
Known to work: 10.2.0, 11.0
Workaround?
The anonymous typename is for some SFINAE stuff, and I want a workaround to make it compile on older version of GCC.
As is similarly asked and answered in the comments to the bug report:
Igor Chorazewicz 2020-09-08 12:17:32 UTC
[...] Also, do you by any chance, have any ideas how to workaround it for now?
**Vorfeed Canal 2020-09-09 13:32:20 UTC **
Why couldn't you use std::enable_if in it's usual (for functions) place?
Like this:
template <typename K, typename... Args>
auto f(K&& k, Args&&... args) -> std::enable_if_t<true, void>
{
}
you can remove the SFINAE-intended defaulted type template argument and apply SFINAE for the return type of the function instead, using trailing return type syntax.
Relevance to rvalue references?
Note that albeit the author of the bug report mentions problems with rvalue references in the title of the bug report, the failing example (fixed in GCC trunk) given in the report
#include <type_traits>
template <typename... Args>
void f(int &&a, Args&&... args)
{
}
template <typename K, typename... Args, typename = typename std::enable_if<true, K>::type>
void f(K&& k, Args&&... args)
{
}
int main() {
f(1, 2);
return 0;
}
likewise fails(/is fixed) if we remove the rvalue references for the arguments of the f overloads, and these were likely not the root cause for this issue.
I have defined a typelist like this:
template <typename ... Types> struct typelist {};
using my_list = typelist<int, double, bool, float>;
Now I have a function template, e.g.
template<typename T>
void foo() {
std::cout << typeid(T).name() << std::endl;
}
and want to call this for every type in the typelist:
foo<int>();
foo<double>();
foo<bool>();
foo<float>();
I tried to find a recursive way to solve this, but I am having trouble to define the correct, probably nested, variadic templates for the required foo functions. Do you have any hints for a neat solution to this problem?
template<class... Types> auto foo_foreach(typelist<Types...>) {
return (foo<Types>(), ...);
}
int main() {
foo_foreach(my_list{});
}
For a real oldschool, well, use template recursion you've attempted before:
void foo_foreach(typelist<>) {}
template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>);
template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>) {
foo<Head>();
foo_foreach(typelist<Tail...>{});
}
Here is a c++20 answer only that uses lambda template.
template <typename... Ts, typename C>
constexpr void for_types(C&& c) {
(c.template operator()<Ts>(), ...);
}
for_types<int, float, char>([]<typename T>()
{
std::cout << typeid(T).name() << std::endl;
});
If you need this to work with C++14 then you can use the initializer_list trick to avoid a C++17 fold expression. This will hopefully be cheaper to compile than a recursive approach:
template<class... Ts> void foo_foreach(typelist<Ts...>) {
(void) std::initializer_list<int>{(foo<Ts>(), 0)...};
}
int main() {
foo_foreach(my_list{});
}
Godbolt example: https://godbolt.org/z/o91Th466s
There is a good explanation of the initializer_list trick at https://blog.tartanllama.xyz/exploding-tuples-fold-expressions/
From that article:
[...] parameter packs can only be expanded in contexts which expect a syntactic list, such as initializers and function call arguments. You can’t just expand them bare in a function body. In C++17, this problem has a nice solution, but prior to that we need to use some pretty horrible hacks. [...] one possibility [...] uses std::initializer_list to create a context in which the parameter pack can be expanded.
The trick is the , 0 inside the initializer_list initializer, which evaluates the function call, and uses 0 as the initializer value.
Just wondering why is this invalid:
#include <iostream>
template <std::size_t... Is>
void foo(Is&&... args) {
std::cout << "foo called with " << sizeof...(Is) << "params\n";
}
int main() {
foo(1, 2, 3, 4);
}
It seems a perfectly reasonable example, yet it fails on any compiler I can get my hands on.
If I substitute size_t for class the example works as expected. I've also tried using the new auto template parameter but no online compiler accepts this so I don't know if this an invalid use case or a conformance issue.
It's not valid C++, that's why.
If you instantiate that function template with the template arguments 1, 2, 3, 4 then after substituting the arguments into the template you get the signature:
void foo(1&&, 2&&, 3&&, 4&&);
That's clearly not a valid function.
If you want to write a function template that accepts any number of arguments but only if they are of the right type, you can do that like this in C++17:
template<typename T>
using is_size_t = std::is_same<T, std::size_t>;
template<typename... T>
std::enable_if_t<std::conjunction<is_size_t<T>...>::value>>
foo(T&&... args);
Or alternatively (also using C++17):
template<typename... T>
std::enable_if_t<(std::is_same_v<std::size_t, T> && ...)>
foo(T&&... args);
For C++14 you need to implement std::conjunction yourself, e.g. using the and_ template from p0032r1
I've been working with another language lately and totally pulled a Monika there. Just to complement Jonathan's answer, (thanks for the explanation and the comments) this is how to ensure all parameters are of size_t type (what I was actually trying to do) using concepts:
template <class... Is>
requires (std::is_same<Is, int>::value && ...)
void foo(Is&&... args) { /*...*/ }
Or even (ma fav) by defining a dedicated concept
template <class T> concept bool Integer = std::is_same<T, int>::value;
template <Integer... Is> void foo(Is&&... args) { /*...*/ }
// ^^^^^^^awesome
Live
I have seen a lot of links introducing the variadic templates. But I have never seen any compilable example that demonstrates this approach.
Could someone provide me with some links in which such compilable examples can be found?
One of the simplest possible examples is the following implementation of max which isn't even templated on types.
int maximum(int n)
{
return n;
}
template<typename... Args>
int maximum(int n, Args... args)
{
return max(n, maximum(args...));
}
Only slightly more complex is the canonical printf implementation:
void printf(const char *s)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
throw "invalid format string: missing arguments";
std::cout << *s++;
}
}
template<typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
{
std::cout << value;
printf(s, args...); // call even when *s == 0 to detect extra arguments
return;
}
std::cout << *s++;
}
throw "extra arguments provided to printf";
}
Variadic templates are a C++0x feature that primarily targets authors of generic libraries. I would not expect to see them in "user code". For example, in the C++0x standard library they are used in a lot of places: std::function, std::async, std::reference_wrapper, std::tuple, std::packaged_task, ...
To give you an example I'll show you how a reference_wrapper might be implemented with respect to variadic templates:
template<class T>
class reference_wrapper
{
T *ptr;
public:
explicit reference_wrapper(T& thing) : ptr(&thing) {}
explicit reference_wrapper(T&& ) = delete;
operator T&() const {return *ptr;}
template<class... Args>
decltype( declval<T&>()(declval<Args>()...) )
operator()(Args&&... args) const
{
return (*ptr)(forward<Args>(args)...);
}
};
This is not perfectly conforming to the standard draft but it is supposed to be compilable with little modification. It demonstrates multiple C++0x features:
deleted functions (disabling the constructor for rvalues)
rvalue references (detecting rvalue arguments to the constructor, perfect forwarding)
type deduction via decltype
standard library function template declval to create objects for the purpose of building an expression for decltype (GCC does not yet offer this function template. You have to write it yourself)
variadic templates (accepting an arbitrary number of parameters)
The purpose of the variadic member template is to forward arguments to the object referred to by ptr. This should work in case T is a function pointer type or a class type with overloaded function call operator.
cheers!
s
Wikipedia is good starting point.
Gregor, Douglas; Jaakko Järvi; Gary Powell (9 September 2006). "Variadic Templates (Revision 3)".
A very simple example of variadic template:
Suppose we want to have a function which takes variable number of arguments and prints them all. For ex:
print("Hello", 1, 3.14, 5L);
For that functionality to work, we would basically require two functions:
First one, a function which takes variable number of arguments:
template<typename T, typename... Args>
void print(T t, Args ...args){
std::cout << t << ", ";
print(args...);
}
Some explanation:
1.) Parameter Packs denoted by ellipsis(...), that appear in parameter list.
typename...Args
| | << Optional whitespace. Can have multiple whitespaces in between them
Args...args
That means, these all are same.
typename ...args
typename...args
typename ... args
So, you don't have to worry about the correct position of the whitespace in there. Though, IMO at most one whitespace should be used as a best practice.
2.) Pack Expansion: A pattern followed by an ellipsis.
print(args...); //expand when you wish to use them
3.) Parameter pack accepts zero or more template args. So, print(T t, Args... args) accepts one or more args.
Once you understand that, we can visualize the call flow as below:
print("Hello", 1, 3.14, 5L);
translates into:
print(string, int, float, long);
which calls
print(int, float, long);
which calls
print(float, long); // say Level 2
which calls
print(long); // say Level 1
which calls
print(); // say Level 0
If you have followed the Point#3 carefully, you must have realized that print(T t, Args... args) can't handle call at Level 0.
So we need another function here with same name to catch up at any level >=0.
Second one, a function to grab the call at the top of call stack:
Catch at level 0:
void print(){}
or, Catch at level 1:
template<typename T>
void print(T t){ std::cout << t;}
or, Catch at level 2:
template<typename T, typename U>
void print(T t, U u){ std::cout << t << ", " << u;}
so on...
Any of these would work. Hope this helps you next time you go about writing such function or class.
This is an example of variadic templates that I put up on my blog:
http://thenewcpp.wordpress.com/2011/11/23/variadic-templates-part-1-2/
It compiles. It demonstrates finding the largest type from a group of types.
#include <type_traits>
template <typename... Args>
struct find_biggest;
//the biggest of one thing is that one thing
template <typename First>
struct find_biggest<First>
{
typedef First type;
};
//the biggest of everything in Args and First
template <typename First, typename... Args>
struct find_biggest<First, Args...>
{
typedef typename find_biggest<Args...>::type next;
typedef typename std::conditional
<
sizeof(First) >= sizeof(next),
First,
next
>::type type;
};
Variadic templates are part of the C++0x standard which is not yet officially released. They are supported by gcc since version 4.3, but you need to enable support for C++0x by adding the compiler switch -std=c++0x.
Before C++11, you can create template only with the fixed count of parameters.
Firts template for the function with one parameter.
Second template for the function with two parameters.
... i.e.
Since C++11 you can write only one template, compiler will generate required function itself.
Good example
http://eli.thegreenplace.net/2014/variadic-templates-in-c/
another syntax: expanding, e.g.
template<typename VAL, typename... KEYS>
class MyMaps
{
typedef std::tuple< std::map<KEYS,VAL>... > Maps;
}
hence:
MyMaps<int,int,string>:Maps
is now actually:
std::tuple<std::map<int,int>,std::map<string,int> >