Using Variable Argument List in a Template - c++

I have been trying to figure out the problem that I am facing in the following piece of code.
#include <iostream>
#include <stdarg.h>
#include <vector>
using namespace std;
template <typename T>
class C {
vector<T> vec;
public:
void PrintValues(int size, T val, ...){
va_list v;
va_start(v,val);
for ( int i = 0 ; i < size ; i++ ) {
T p = va_arg(v,T);
vec.push_back(p);
cout<<p<<" ";
}
va_end(v);
}
};
int main() {
C<int> a;
C<char *> b;
cout<<endl;
a.PrintValues(10,1,4,6,2,8,5,3,7,10,9);
cout<<endl;
b.PrintValues(10,"a","b","c","d","e","f","g","h","i","j");
cout<<endl;
return 0;
}
I compiled this code on my Ubuntu 10.04 desktop using g++ 4.4.3.
The code compiled with the following warning
testcode.cpp: In function ‘int main()’:
testcode.cpp:25: warning: deprecated conversion from string constant to ‘char*’
While I was expecting an output like
1 4 6 2 8 5 3 7 10 9
a b c d e f g h i j
I actually got the following output
4 6 2 8 5 3 7 10 9 0
b c d e f g h i j `*#
Can someone please provide me with some pointers regarding why the first element in the list is skipped? I know that I can also do the same thing without using the variable argument list, but I am just trying out if this is possible.

Your first element is being put into the T val parameter, and not into va_list v;. This is because va_start(v, val) sets up v with the var-args which start after val, not including val. Have some documentation

You are eating the first part of your list in val argument and so you actually have one less element in your list than you are indicating with size:
void PrintValues(int size, T val, ...)
^^^^^
So in the first case val will be 1 and the second case a. One potential fix would be to drop the val arg:
void PrintValues(int size, ...)
and alter your va_start:
va_start(v,size);
I realize you are just experimenting but this is not type safe and we have variadic templates with C++11 now. Although since you are using only one type std:::initializer_list is also a viable alternative, as mentioned in the previous link.

Related

Make the compiler deduce the parameter of a function before compilation

Here is an example of my problem.
#include <stdio.h>
//template<std::size_t A> <-- Tried to solve the problem by using template
void func1(const int power){
const int length = 1 << power;
int twoDArrayA[length][length];
for (int j = 0; j < power; j++)
{
/* Code */
}
}
int main() {
func1(4);
func1(3);
func1(2);
}
I wonder if I could somehow allow the compiler to deduce parameter power in func1 before it compiles. So instead of compiles one function, it compiles 4 functions in the format of func1 with different power value.
The reason for this is because I would like to use Vitis HLS to unroll the loop and partition the matrix so that it could be implemented onto a FPGA, where a variable-length loop or array cannot work properly.
You can do this with a template, but you've got the wrong syntax. It should be:
template<std::size_t power>
void func1(){
const std::size_t length = 1 << power;
int twoDArrayA[length][length];
...
}
int main() {
func1<4>();
...
}
Note that your variable length array (VLA) is legal C++ if length is a compile-time constant (as it is here). Nevertheless, std::array would be a better bet.
PS: Thanks for telling us why you want to do this. That was a nice touch.

What is the difference between for(auto& x:A) and for(auto &x:A) in C++ [duplicate]

This question already has answers here:
What's the semantically accurate position for the ampersand in C++ references
(3 answers)
Closed 2 years ago.
I have an int type array, and I want to reference its values using a range based for loop, but I can't find the difference between using for(auto& x:A) and for(auto &x:A). Both are valid in my compiler and give the same output. Is there any diference?
Here is the code i'm using and the output:
#include "pch.h"
#include <iostream>
using namespace std;
int main()
{
int A[10] = {0,1,2,3,4,5,6,7,8,9};
//Using any of the two following lines, there seems to be no diference in the output.
//for (auto& x : A) x=1;
//for (auto &x : A) x=1;
for (auto x : A) cout << x << " ";
}
And the output is:
1 1 1 1 1 1 1 1 1 1
but I can't find the difference between using for(auto& x:A) and for(auto &x:A)
No differences.
Same as pointer type: int* p or int *p are the same thing.
Both styles are correct. However, see this which indicates it may be better for & and * to be closer to the variable name (ie prefer the later style):
https://www.quora.com/Where-should-I-put-the-asterisk-for-pointers-in-C++-Is-it-int-ptr-int--ptr-or-int-*ptr
In my experience with many clients, large and small, and several
different coding standards, the overwhelming majority attach the
asterisk to the variable name (i.e., int *ptr)

The difference between int a[5] and int (&a)[5] in template parameter deduction

This question is about functions that take arrays of statically known size.
Take for example the following minimal program:
#include <iostream>
template<size_t N>
void arrfun_a(int a[N])
{
for(size_t i = 0; i < N; ++i)
std::cout << a[i]++ << " ";
}
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
arrfun_a<5>(a);
std::cout << std::endl;
arrfun_a<5>(a);
return 0;
}
Which, when run, prints the expected result:
2 3 4 5 6
3 4 5 6 7
However, when I tried to have my compiler (VS 2010) deduce the 5, it could not deduce template argument for 'int [n]' from 'int [5]'.
A bit of research resulted in the updated arrfun_b where the template parameter deduction works:
template<size_t n>
void arrfun_b(int (&a)[n])
{
for(size_t i = 0; i < n; ++i)
std::cout << ++(a[i]) << std::endl;
}
The result of the program is the same, whether arrfun_a or arrfun_b is called.
So far, the only difference I have found is whether the template argument deduction works and if it is possible to call the function with an N that is not 5...
The compiler silently changes the type of function argument int a[N] to int *a and thus loses the size of the array. int(&a)[5] is truly a reference to an array of size 5, and cannot be passed an array of any other size.
I think its the difference between a reference and a pointer.
arrfun_a passes a pointer to int.
arrfun_b passes a reference to an array of ints.

heapsort implementation in c++

i have following code for heapsort
#include <iostream>
using namespace std;
void exch(int a[],int i,int j){
int s=a[i];
a[i]=a[j];
a[j]=s;
}
void sink(int a[],int k,int n){
//int n=sizeof(a)/sizeof(int);
while(2*k<=n){
int j=2*k;
if (j<n && (a[j]<a[j+1])) j++;
if (a[k]>=a[j]) break;
exch(a,k,j);
k=j;
}
}
void heapsort(int a[]){
int n=sizeof(a)/sizeof(int);
for (int k=n/2;k>=1;k--)
sink(a,k,n);
while(n>1){
exch(a,1,n--);
sink(a,1,n);
}
}
int main(){
int a[]={12,3,5,1,67,10,9.20};
int n=sizeof(a)/sizeof(int);
heapsort(a);
for (int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
but result it shows me looks like this
12 3 5 1 67 10 9 Press any key to continue . . .
also look that in my array total number is 8 and here it shows me 7 as output, i think core of this problem should be this
1>c:\users\datuashvili\documents\visual studio 2010\projects\heap\heap\heap.cpp(36): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data
it seams that possible loss of data while converting from double to int force code works incorrectly,am i correct or wrong?please help me
You wrote a . instead of a , between the 9 and 20:
int a[]={12,3,5,1,67,10,9.20};
This results in 7 numbers, the last of which is the double 9.20 which gets converted to an int.
Additionally, this code is wrong:
void heapsort(int a[]){
int n=sizeof(a)/sizeof(int);
Array arguments are actually passed as pointers, so sizeof(a) won't give you the correct result. You should pass in the array size as an additional parameter instead.
One problem I can see immediately is here:
void heapsort(int a[]){
int n=sizeof(a)/sizeof(int);
You cannot pass an entire array as a parameter to a function in C/C++. The parameter syntax int a[] is, of course, confusing, but in fact it's equivalent to int* a. heapsort() can't know the size of the array to which a points. You have to pass the size in as a separate parameter.
In addition to all the other comments (sizeof(a), passing [] as arguments, having a . in the init-list), you want to write C++-code, right? But it looks quite C'ish, except for the iostream. Thereore:
use std::vector<int> from #include <vector> (add elements with push_back for example)
pass it as as a reference, i.e. void heapsort(std::vector<int> &a)
consider using std::swap( a[i], a[j] ); instead of exch

Function overloading

I found this code , and i m not sure that whether overloading should happen or not.
void print( int (*arr)[6], int size );
void print( int (*arr)[5], int size );
what happens if I pass pointer to an array of 4 elements , to it should come...
any thread will be helpful.
Overloading will happen, and passing the pointer to the array of 4 int's will not match either function. It's clearer if you write them as the equivalent form:
void print( int arr[][6], int size );
void print( int arr[][5], int size );
An N×4 array can be decayed to a pointer to array of 4 int's. And it's well known that 2D arrays having different 2nd dimensions are incompatible.
KennyTM's answer is the correct one. Here's an additional thought, though, based on the fact that your question comes with a C++ tag. In C++, you can use templates with non-type arguments to find out array dimensions:
#include <iostream>
template< std::size_t N >
void print(int (&arr)[N]) {std::cout << N << '\n';}
int main()
{
int arr[6];
print(arr);
return 0;
}
The call would be ambiguous as none of the two overloads would be able to convert to int (*arr)[4]. You need to pass in an element of 5 or 6 elements explicitly.
VS2008 gives:
error C2665: 'print' : none of the 2 overloads could convert all the argument types
(2088): could be 'void print(int (*)[5],int)'
(2093): or 'void print(int (*)[6],int)'
while trying to match the argument list '(int (*)[4], int)'
Hope that helps.