I want to calculate the sum of all arguments (non-type parameters) passed through a template. I compiled the following program with: g++ -std=c++17 -g -Wall -o main main.cpp. It seems that I miss something, because I get this errors when compiling:
error: call of overloaded ‘func<N_0>()’ is ambiguous
std::cout << func<N_0>() << std::endl;
error: call of overloaded ‘func<22>()’ is ambiguous
return N + func<Next... >();
#include <iostream>
using namespace std;
template <std::size_t T>
std::size_t sum()
{
return T;
}
template <std::size_t N, std::size_t ...Next>
std::size_t sum()
{
return N + sum<Next... >();
}
int main()
{
const size_t N_0 = 4;
const size_t N_1 = 11;
const size_t N_2 = 22;
std::cout << sum<N_0>() << std::endl;
std::cout << sum<N_0, N_1, N_2>() << std::endl;
return 0;
}
I found a lot of examples like this:
#include <iostream>
template<typename T>
T adder(T first) {
return first;
}
template<typename T, typename... Args>
T adder(T first, Args... args) {
return first + adder(args...);
}
int main() {
const int c = adder(1, 8, 4);
std::cout << c << '\n';
return 0;
}
I am very curious why my code is not working.
In both the first and second code example, calling the function with only one (template) argument results in both function templates being viable. The packs will simply be empty.
However, in overload resolution in the second example the variadic template is considered less specialized than the non-variadic one, basically because the set of possible arguments to call it with is a superset of those that the non-variadic one can be called with. This is only because of the parameter pack in the function parameters. Therefore overload resolution will prefer the non-variadic template as a tie-breaker.
This ordering doesn't apply to your first code example, where the function parameters of both templates are the same.
Therefore overload resolution with a single (template) argument is ambiguous in your first code example, but not ambiguous in the second.
You can specify that the variadic template requires at least two arguments to resolve the ambiguity:
template <std::size_t N, std::size_t M, std::size_t ...Next>
std::size_t sum()
{
// May wrap-around to zero
return N + sum<M, Next... >();
}
However, in C++17 and later the whole sum construct can be simplified by use of fold expressions to:
template <std::size_t ...Ns>
std::size_t sum()
{
// May wrap-around to zero
return (Ns + ...);
}
(This function should probably be marked noexcept and constexpr in C++17 or consteval in C++20 and one should be careful with many/large arguments since the addition will silently wrap-around if the sum becomes too large for std::size_t to hold.)
I'm learning C++20 concept/requires. I would like to implement a function for getting the sum of an integer list with template meta programming:
sum<IntList<1, 2, 3>>();
As it's known that C++ standards don't allow function partial specialization, I would like to use C++20 concept/requires to the similar stuff as function partial specialization.
Here is my code:
#include <iostream>
template<int...N>
class IntList;
template<int...N>
concept IsIntList = IntList<N...>{};
template<typename T>
int sum() {
return 0;
}
template<int...N>
requires IsIntList<N...>
int sum() {
return (N + ...);
}
int main() {
std::cout << sum<IntList<1, 2>>() << std::endl;
return 0;
}
But it could not produce what I want. Put my code in C++ Insights. The first sum is instantiated, instead of the second sum.
Here is the result of C++Insights:
#include <iostream>
template<int...N>
class IntList;
template<int...N>
concept IsIntList = IntList<N...>{};
template<typename T>
int sum() {
return 0;
}
/* First instantiated from: insights.cpp:21 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
int sum<IntList<1, 2> >()
{
return 0;
}
#endif
template<int...N>
requires IsIntList<N...>
int sum() {
return (N + ...);
}
int main()
{
std::cout.operator<<(sum<IntList<1, 2> >()).operator<<(std::endl);
return 0;
}
What's the correct way to solve this problem? Thanks!
The central problem you're encountering is that you have a type template parameter whose type you want to be constrained to being some specialization of some template. That's not a thing you can do with a requires clause. At least, not easily.
It's best to avoid this problem. You're only encountering it because you insist that sum's template parameter must be some specialization of IntList instead of the integers themselves directly. The best way to handle this is by ditching this assumption:
template<int... Ints>
constexpr int sum(IntList<Ints...>)
{ return (0 + ... + Ints); }
You then call this function as so: sum(IntList<1, 2>{}). Note that IntList needs to have a constexpr default constructor.
Your definition of the concept of IsIntList is wrong, it only evaluates the value of IntList<N...>{}, and since IntList is not a bool type, IsIntList always return false.
You should use template partial specialization to define the IsIntList.
template<int...N>
class IntList;
template<class T>
inline constexpr bool IsIntList = false;
template<int...N>
inline constexpr bool IsIntList<IntList<N...>> = true;
For a specialized version of the sum, just constrain IsIntList<T> to be true, then you can extract the value of the IntList with the help of a tag class and template lambda to calculate the sum.
template<class>
struct tag{};
template<class T>
requires IsIntList<T>
int sum() {
return []<int...N>(tag<IntList<N...>>)
{ return (N + ... + 0); }(tag<T>{});
}
Demo.
Suppose I want to define a C++ function that has no Input Parameters within bracket, but within the <> argument. I have a Parameter pack as Input Arguments. Meaning that I have to write, for example, a function
int calculate<args...>()
{
return 1 + calculate<some_arg,args...>();
}
And also a base case implementation I have to give. However, I am confronted with a lot of Compiler Errors, because I don't know how to write such a form of recursion out properly. What I have to write before the above function declaration?
template<int... args>
(if data type of args is int; any other data type is also possible in a similar way)? Or what I have to write to avoid Compiler Errors? I also tried
template<int some_arg,int... args>
But I don't know also how to deal with variadic templates (how to unpack them). Any help?
EDIT:
My attempt for one Special case
template<bool... dg>
int calculate<0>()
{
return 1;
}
Error message for this is:
error: expected initializer before ‘<’ token
But I don't know also how to deal with variadic templates (how to unpack them). Any help?
As of C++17 you needn't resort to recursion, but can use pack expansion:
#include <iostream>
template<int ...Args>
constexpr int calculate() {
return (Args + ...);
}
int main() {
std::cout << calculate<1, 2, 3>(); // 6
}
If you want to allow other types of non-type template parameters, you can make use of a placeholder type (auto) for non-type template parameters, also a C++17 feature:
template<auto ...Args>
constexpr auto calculate() {
return (Args + ...);
}
As you cannot partially specialize function templates, you will have to use delegation to a class template if you want to provide different implementations for different specializations:
#include <iostream>
#include <ios>
template<auto ...Args>
struct calculate_impl {
static constexpr auto calc() { return (Args + ...); }
};
template<bool ...Args>
struct calculate_impl<Args...> {
static constexpr bool calc() { return (Args && ...); }
};
template<auto ...Args>
constexpr auto calculate() {
return calculate_impl<Args...>::calc();
}
int main() {
std::cout << calculate<1, 2, 3>(); // 6
std::cout << std::boolalpha
<< "\n" << calculate<false,true>() // false
<< "\n" << calculate<true, true>(); // true
}
If you're using C++17+: refer to dfrib's answer
Here's how you would implement a function to add the elements of a parameter pack using template recursion
template<int arg>
constexpr int add()
{
return arg;
}
template<int arg1, int arg2, int... args>
constexpr int add()
{
return arg1 + add<arg2, args...>();
}
Regarding if you wanted to create a special case
template<int arg>
constexpr int calculate()
{
return arg;
}
template<> int calculate<0>() { return 1; } // special case
template<int arg1, int arg2, int... args>
constexpr int calculate()
{
return calculate<arg1>() + calculate<arg2,args...>();
}
This would make it to where every time you have a zero in you argument list, it will add 1 instead of 0
Another way to do recursion allows you to do it in a single function, utilizing the sizeof... operator:
template<int lhs, int... rhs>
int add()
{
if constexpr(sizeof...(rhs))
{
return lhs + add<rhs...>();
}
else
{
return lhs;
}
}
This also requires C++17 for if constexpr, but it can do things that fold expressions might not be able to.
I've been looking into how to declare functions or class members with a variable number of argument, and came across variadic functions, however I was wondering if there was some way to access the number of arguments pass to the function, without having to pass it directly as a first argument, as most of the documentation presents. I am also aware that I can use either variadic templates or std::initializer_list, but since I was looking to pass multiple arguments of the same type, those seem both too generic and/or with a convoluted syntax.
#include <cstdarg>
bool func(int args...) {
va_list list;
va_start(list, args);
int val = args;
while(val >=0) {
std::cout << val << std::endl;
val = va_arg(list, int);
}
return true;
}
bool other_func(int c, int args...) {
va_list list;
va_start(list, args);
int val = args;
for (int i = 0; i<c; i++) {
std::cout << val << std::endl;
val = va_arg(list, int);
}
return true;
}
int main(int argc, char const *argv[]) {
func(2, 7, 47, -1, 23 /* ignored */);
other_func(3 /* n of parameters */, 2, 7, 47);
return 0;
}
In these particular example, func loops over the input arguments until a negative value is found (in order to illustrate the issue and force a stop flag) while other_func requires the number of arguments to be passed as the first argument. Both these implementations seemed to me rather flawed and unsafe, is there a better way to approach this?
since I was looking to pass multiple arguments of the same type
That's exactly what std::initialiser_list<int> would give you.
You seem to be mistaken about variadic functions. The declaration int args... doesn't mean "some amount of int arguments", instead it means "one int named args, followed by any number of arguments of any type"
If you use C-style varargs then no, you can only parse the argument list one at a time.
If you have the option of c++11 then you could use a variadic template function instead and use the sizeof... operator to get the size of the argument pack.
template<typename ... Args>
void func(char * leading, Args const & ... args)
{
/* sizeof...(Args) will give you the number of arguments */
}
If you have C++17 available to you, this can all be done at compile time with a variadic non-type template argument and a fold expression: (Live Demo)
template<int... args>
constexpr bool func() {
return ((args < 0) || ...);
}
int main() {
static_assert(func<2, 7, 47, -1, 23>());
static_assert(!func<1, 2, 3>());
return 0;
}
(and if you're using C++20, you can enforce compile-time computation with consteval instead of constexpr. Demo 2)
If you're stuck with C++11, then you can still do it at compile-time, but we'll need some more boilerplate (Live Demo 3)
#include <type_traits>
namespace detail
{
template<bool...>
struct disjunction;
template<bool b>
struct disjunction<b> : std::integral_constant<bool, b>
{};
template<bool left, bool... Bs>
struct disjunction<left, Bs...> : std::conditional<left, disjunction<left>, disjunction<Bs...>>::type
{};
}
template<int... args>
constexpr bool func() {
static_assert(sizeof...(args) > 0, "Need to pass more than 1 integer");
return detail::disjunction<(args < 0)...>::value;
}
int main() {
static_assert(func<2, 7, 47, -1, 23>(), "There is one negative number");
static_assert(!func<1, 2, 3>(), "There aren't any negative numbers");
return 0;
}
No, there is no standard-conforming way to detect the number of arguments passed to a (C-style) variadic function. You would have to pass the number in an initial argument, or use some sort of terminator that could be recognized as the end of the sequence. It would be preferable to use C++ facilities for this.
I'm trying to find a method to iterate over an a pack variadic template argument list.
Now as with all iterations, you need some sort of method of knowing how many arguments are in the packed list, and more importantly how to individually get data from a packed argument list.
The general idea is to iterate over the list, store all data of type int into a vector, store all data of type char* into a vector, and store all data of type float, into a vector. During this process there also needs to be a seperate vector that stores individual chars of what order the arguments went in. As an example, when you push_back(a_float), you're also doing a push_back('f') which is simply storing an individual char to know the order of the data. I could also use a std::string here and simply use +=. The vector was just used as an example.
Now the way the thing is designed is the function itself is constructed using a macro, despite the evil intentions, it's required, as this is an experiment. So it's literally impossible to use a recursive call, since the actual implementation that will house all this will be expanded at compile time; and you cannot recruse a macro.
Despite all possible attempts, I'm still stuck at figuring out how to actually do this. So instead I'm using a more convoluted method that involves constructing a type, and passing that type into the varadic template, expanding it inside a vector and then simply iterating that. However I do not want to have to call the function like:
foo(arg(1), arg(2.0f), arg("three");
So the real question is how can I do without such? To give you guys a better understanding of what the code is actually doing, I've pasted the optimistic approach that I'm currently using.
struct any {
void do_i(int e) { INT = e; }
void do_f(float e) { FLOAT = e; }
void do_s(char* e) { STRING = e; }
int INT;
float FLOAT;
char *STRING;
};
template<typename T> struct get { T operator()(const any& t) { return T(); } };
template<> struct get<int> { int operator()(const any& t) { return t.INT; } };
template<> struct get<float> { float operator()(const any& t) { return t.FLOAT; } };
template<> struct get<char*> { char* operator()(const any& t) { return t.STRING; } };
#define def(name) \
template<typename... T> \
auto name (T... argv) -> any { \
std::initializer_list<any> argin = { argv... }; \
std::vector<any> args = argin;
#define get(name,T) get<T>()(args[name])
#define end }
any arg(int a) { any arg; arg.INT = a; return arg; }
any arg(float f) { any arg; arg.FLOAT = f; return arg; }
any arg(char* s) { any arg; arg.STRING = s; return arg; }
I know this is nasty, however it's a pure experiment, and will not be used in production code. It's purely an idea. It could probably be done a better way. But an example of how you would use this system:
def(foo)
int data = get(0, int);
std::cout << data << std::endl;
end
looks a lot like python. it works too, but the only problem is how you call this function.
Heres a quick example:
foo(arg(1000));
I'm required to construct a new any type, which is highly aesthetic, but thats not to say those macros are not either. Aside the point, I just want to the option of doing:
foo(1000);
I know it can be done, I just need some sort of iteration method, or more importantly some std::get method for packed variadic template argument lists. Which I'm sure can be done.
Also to note, I'm well aware that this is not exactly type friendly, as I'm only supporting int,float,char* and thats okay with me. I'm not requiring anything else, and I'll add checks to use type_traits to validate that the arguments passed are indeed the correct ones to produce a compile time error if data is incorrect. This is purely not an issue. I also don't need support for anything other then these POD types.
It would be highly apprecaited if I could get some constructive help, opposed to arguments about my purely illogical and stupid use of macros and POD only types. I'm well aware of how fragile and broken the code is. This is merley an experiment, and I can later rectify issues with non-POD data, and make it more type-safe and useable.
Thanks for your undertstanding, and I'm looking forward to help.
If your inputs are all of the same type, see OMGtechy's great answer.
For mixed-types we can use fold expressions (introduced in c++17) with a callable (in this case, a lambda):
#include <iostream>
template <class ... Ts>
void Foo (Ts && ... inputs)
{
int i = 0;
([&]
{
// Do things in your "loop" lambda
++i;
std::cout << "input " << i << " = " << inputs << std::endl;
} (), ...);
}
int main ()
{
Foo(2, 3, 4u, (int64_t) 9, 'a', 2.3);
}
Live demo
(Thanks to glades for pointing out in the comments that I didn't need to explicitly pass inputs to the lambda. This made it a lot neater.)
If you need return/breaks in your loop, here are some workarounds:
Demo using try/throw. Note that throws can cause tremendous slow down of this function; so only use this option if speed isn't important, or the break/returns are genuinely exceptional.
Demo using variable/if switches.
These latter answers are honestly a code smell, but shows it's general-purpose.
If you want to wrap arguments to any, you can use the following setup. I also made the any class a bit more usable, although it isn't technically an any class.
#include <vector>
#include <iostream>
struct any {
enum type {Int, Float, String};
any(int e) { m_data.INT = e; m_type = Int;}
any(float e) { m_data.FLOAT = e; m_type = Float;}
any(char* e) { m_data.STRING = e; m_type = String;}
type get_type() const { return m_type; }
int get_int() const { return m_data.INT; }
float get_float() const { return m_data.FLOAT; }
char* get_string() const { return m_data.STRING; }
private:
type m_type;
union {
int INT;
float FLOAT;
char *STRING;
} m_data;
};
template <class ...Args>
void foo_imp(const Args&... args)
{
std::vector<any> vec = {args...};
for (unsigned i = 0; i < vec.size(); ++i) {
switch (vec[i].get_type()) {
case any::Int: std::cout << vec[i].get_int() << '\n'; break;
case any::Float: std::cout << vec[i].get_float() << '\n'; break;
case any::String: std::cout << vec[i].get_string() << '\n'; break;
}
}
}
template <class ...Args>
void foo(Args... args)
{
foo_imp(any(args)...); //pass each arg to any constructor, and call foo_imp with resulting any objects
}
int main()
{
char s[] = "Hello";
foo(1, 3.4f, s);
}
It is however possible to write functions to access the nth argument in a variadic template function and to apply a function to each argument, which might be a better way of doing whatever you want to achieve.
Range based for loops are wonderful:
#include <iostream>
#include <any>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p.type().name() << std::endl;
}
}
int main() {
printVariadic(std::any(42), std::any('?'), std::any("C++"));
}
For me, this produces the output:
i
c
PKc
Here's an example without std::any, which might be easier to understand for those not familiar with std::type_info:
#include <iostream>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p << std::endl;
}
}
int main() {
printVariadic(1, 2, 3);
}
As you might expect, this produces:
1
2
3
You can create a container of it by initializing it with your parameter pack between {}. As long as the type of params... is homogeneous or at least convertable to the element type of your container, it will work. (tested with g++ 4.6.1)
#include <array>
template <class... Params>
void f(Params... params) {
std::array<int, sizeof...(params)> list = {params...};
}
This is not how one would typically use Variadic templates, not at all.
Iterations over a variadic pack is not possible, as per the language rules, so you need to turn toward recursion.
class Stock
{
public:
bool isInt(size_t i) { return _indexes.at(i).first == Int; }
int getInt(size_t i) { assert(isInt(i)); return _ints.at(_indexes.at(i).second); }
// push (a)
template <typename... Args>
void push(int i, Args... args) {
_indexes.push_back(std::make_pair(Int, _ints.size()));
_ints.push_back(i);
this->push(args...);
}
// push (b)
template <typename... Args>
void push(float f, Args... args) {
_indexes.push_back(std::make_pair(Float, _floats.size()));
_floats.push_back(f);
this->push(args...);
}
private:
// push (c)
void push() {}
enum Type { Int, Float; };
typedef size_t Index;
std::vector<std::pair<Type,Index>> _indexes;
std::vector<int> _ints;
std::vector<float> _floats;
};
Example (in action), suppose we have Stock stock;:
stock.push(1, 3.2f, 4, 5, 4.2f); is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(3.2f, 4, 5, 4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push(4, 5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push();, which is resolved to (c) as there is no argument, thus ending the recursion
Thus:
Adding another type to handle is as simple as adding another overload, changing the first type (for example, std::string const&)
If a completely different type is passed (say Foo), then no overload can be selected, resulting in a compile-time error.
One caveat: Automatic conversion means a double would select overload (b) and a short would select overload (a). If this is not desired, then SFINAE need be introduced which makes the method slightly more complicated (well, their signatures at least), example:
template <typename T, typename... Args>
typename std::enable_if<is_int<T>::value>::type push(T i, Args... args);
Where is_int would be something like:
template <typename T> struct is_int { static bool constexpr value = false; };
template <> struct is_int<int> { static bool constexpr value = true; };
Another alternative, though, would be to consider a variant type. For example:
typedef boost::variant<int, float, std::string> Variant;
It exists already, with all utilities, it can be stored in a vector, copied, etc... and seems really much like what you need, even though it does not use Variadic Templates.
There is no specific feature for it right now but there are some workarounds you can use.
Using initialization list
One workaround uses the fact, that subexpressions of initialization lists are evaluated in order. int a[] = {get1(), get2()} will execute get1 before executing get2. Maybe fold expressions will come handy for similar techniques in the future. To call do() on every argument, you can do something like this:
template <class... Args>
void doSomething(Args... args) {
int x[] = {args.do()...};
}
However, this will only work when do() is returning an int. You can use the comma operator to support operations which do not return a proper value.
template <class... Args>
void doSomething(Args... args) {
int x[] = {(args.do(), 0)...};
}
To do more complex things, you can put them in another function:
template <class Arg>
void process(Arg arg, int &someOtherData) {
// You can do something with arg here.
}
template <class... Args>
void doSomething(Args... args) {
int someOtherData;
int x[] = {(process(args, someOtherData), 0)...};
}
Note that with generic lambdas (C++14), you can define a function to do this boilerplate for you.
template <class F, class... Args>
void do_for(F f, Args... args) {
int x[] = {(f(args), 0)...};
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
Using recursion
Another possibility is to use recursion. Here is a small example that defines a similar function do_for as above.
template <class F, class First, class... Rest>
void do_for(F f, First first, Rest... rest) {
f(first);
do_for(f, rest...);
}
template <class F>
void do_for(F f) {
// Parameter pack is empty.
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
You can't iterate, but you can recurse over the list. Check the printf() example on wikipedia: http://en.wikipedia.org/wiki/C++0x#Variadic_templates
You can use multiple variadic templates, this is a bit messy, but it works and is easy to understand.
You simply have a function with the variadic template like so:
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
And a helper function like so:
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
Now when you call "function" the "helperFunction" will be called and isolate the first passed parameter from the rest, this variable can b used to call another function (or something). Then "function" will be called again and again until there are no more variables left. Note you might have to declare helperClass before "function".
The final code will look like this:
void helperFunction();
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args);
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
The code is not tested.
#include <iostream>
template <typename Fun>
void iteratePack(const Fun&) {}
template <typename Fun, typename Arg, typename ... Args>
void iteratePack(const Fun &fun, Arg &&arg, Args&& ... args)
{
fun(std::forward<Arg>(arg));
iteratePack(fun, std::forward<Args>(args)...);
}
template <typename ... Args>
void test(const Args& ... args)
{
iteratePack([&](auto &arg)
{
std::cout << arg << std::endl;
},
args...);
}
int main()
{
test(20, "hello", 40);
return 0;
}
Output:
20
hello
40