473,379 Members | 1,330 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,379 software developers and data experts.

template with stdarg: enum problem

Hi all!

I'm having trouble with a template function with variable arguments when I
parse an enum type as variable argument. Example:

template <class T>
bool test(int num, ...)
{
va_list ap;
int ind;
bool allequal = true;

va_start(ap, num);
T lastentry((T)va_arg(ap, T));
for(ind=0; ind<num; ind++) {
T entry((T)va_arg(ap, T));
/* do something with T */
if (lastentry != entry)
allequal = false;
lastentry = entry;
}
va_end(ap);

return allequal;
}

Now, if I call this template using an enum, as
typedef enum { ONE, TWO } TestEnum;
if (test<TestEnum>(3, ONE, TWO, ONE) == true)
cout << "all equal!\n";

the compiler says
stdarg.cpp: In function `bool test(int, ...) [with T = TestEnum]':
stdarg.cpp:13: instantiated from here
stdarg.cpp:29: warning: `TestEnum' is promoted to `int' when passed through
`...'
stdarg.cpp:29: warning: (so you should pass `int' not `TestEnum' to
`va_arg')
stdarg.cpp:31: warning: `TestEnum' is promoted to `int' when passed through
`...'

and running the program produces a SIGSEGV.

If I change the va_arg(...) lines to
va_arg(ap, int)

it works, but then the template does not work with other types any more.
Thus, I think I need to detect an enum type somehow, but how could I do
that? I searched through the FAQs and such but couldn't find help.

Thanks very much,
Klaus

Oct 12 '05 #1
8 3432
Klaus Schneider wrote:
Hi all!

I'm having trouble with a template function with variable arguments when I
parse an enum type as variable argument. Example:

template <class T>
bool test(int num, ...)
{
va_list ap;
int ind;
bool allequal = true;

va_start(ap, num);
T lastentry((T)va_arg(ap, T));
for(ind=0; ind<num; ind++) {
T entry((T)va_arg(ap, T));
/* do something with T */
if (lastentry != entry)
allequal = false;
lastentry = entry;
}
va_end(ap);

return allequal;
}

Now, if I call this template using an enum, as
typedef enum { ONE, TWO } TestEnum;
if (test<TestEnum>(3, ONE, TWO, ONE) == true)
cout << "all equal!\n";

the compiler says
stdarg.cpp: In function `bool test(int, ...) [with T = TestEnum]':
stdarg.cpp:13: instantiated from here
stdarg.cpp:29: warning: `TestEnum' is promoted to `int' when passed through
`...'
stdarg.cpp:29: warning: (so you should pass `int' not `TestEnum' to
`va_arg')
stdarg.cpp:31: warning: `TestEnum' is promoted to `int' when passed through
`...'

and running the program produces a SIGSEGV.

If I change the va_arg(...) lines to
va_arg(ap, int)

it works, but then the template does not work with other types any more.
Thus, I think I need to detect an enum type somehow, but how could I do
that? I searched through the FAQs and such but couldn't find help.

Thanks very much,
Klaus


Using va_arg is very much discouraged in C++ because it is not
typesafe. Mixing it with templates, as the FAQs would say, might be
legal but it certainly ain't moral! What is the problem that
necessitates va_args? Can you do it another way?

Cheers! --M

Oct 12 '05 #2
Hi!

I want to create a vector with any number of arguments in one call, i.e.
typedef { TEMPERATURE, POTENTIAL, OUTFLOW } DataType;
Vector<DataType> v(4, TEMPERATURE, POTENTIAL, TEMPERATURE, OUTFLOW);

As it might have any number of elements, it's impossible to use overloading.
If there is another solution, I would prefer that, but I couldn't think of
one.

Thanks very much,
Klaus

mlimber wrote:
Using va_arg is very much discouraged in C++ because it is not
typesafe. Mixing it with templates, as the FAQs would say, might be
legal but it certainly ain't moral! What is the problem that
necessitates va_args? Can you do it another way?


Oct 12 '05 #3
In article <di**********@news.urz.uni-heidelberg.de>,
Klaus Schneider <kl*************@iup.uni-heidelberg.de.x> wrote:
I'm having trouble with a template function with variable arguments when I
parse an enum type as variable argument. Example:

template <class T>
bool test(int num, ...)
{
va_list ap;
int ind;
bool allequal = true;

va_start(ap, num);
T lastentry((T)va_arg(ap, T));
for(ind=0; ind<num; ind++) {
T entry((T)va_arg(ap, T));
/* do something with T */
if (lastentry != entry)
allequal = false;
lastentry = entry;
}
va_end(ap);

return allequal;
}

Now, if I call this template using an enum, as
typedef enum { ONE, TWO } TestEnum;
if (test<TestEnum>(3, ONE, TWO, ONE) == true)
cout << "all equal!\n";

the compiler says
stdarg.cpp: In function `bool test(int, ...) [with T = TestEnum]':
stdarg.cpp:13: instantiated from here
stdarg.cpp:29: warning: `TestEnum' is promoted to `int' when passed through
`...'
stdarg.cpp:29: warning: (so you should pass `int' not `TestEnum' to
`va_arg')
stdarg.cpp:31: warning: `TestEnum' is promoted to `int' when passed through
`...'

and running the program produces a SIGSEGV.

If I change the va_arg(...) lines to
va_arg(ap, int)

it works, but then the template does not work with other types any more.
Thus, I think I need to detect an enum type somehow, but how could I do
that? I searched through the FAQs and such but couldn't find help.


From what I can see, the problem is that in C an enum might be
an int, but in C++ enum's are allowed to be shorter, that is chars.
Furthermore, enum's are promoted when passed to varags functions.
Therefore, your template is conceptually correct but implementation
wise the va_arg results in a misspeak (char vs int), hence the crash.
I seem to recall that gcc has a way to metabolize enum's but don't
know if that's something you want to consider. Then again,
I may not be stareing at your code long enough, and have gotten the
above incorrect.
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Oct 12 '05 #4
In article <di**********@news.urz.uni-heidelberg.de>,
Klaus Schneider <kl*************@iup.uni-heidelberg.de.x> wrote:
Hi!

I want to create a vector with any number of arguments in one call, i.e.
typedef { TEMPERATURE, POTENTIAL, OUTFLOW } DataType;
Vector<DataType> v(4, TEMPERATURE, POTENTIAL, TEMPERATURE, OUTFLOW);

As it might have any number of elements, it's impossible to use overloading.
If there is another solution, I would prefer that, but I couldn't think of
one.


Not knowing where you're full code is eventually going,
it may be that you're requiremens outgrow enum's and move
into say a std::vector or std::map?
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Oct 12 '05 #5
In article <di**********@news.urz.uni-heidelberg.de>,
Klaus Schneider <kl*************@iup.uni-heidelberg.de.x> wrote:
Hi!

I want to create a vector with any number of arguments in one call, i.e.
typedef { TEMPERATURE, POTENTIAL, OUTFLOW } DataType;
Vector<DataType> v(4, TEMPERATURE, POTENTIAL, TEMPERATURE, OUTFLOW);

As it might have any number of elements, it's impossible to use overloading.
If there is another solution, I would prefer that, but I couldn't think of
one.

Greg Comeau <co****@panix.com> wrote: Not knowing where you're full code is eventually going,
it may be that you're requiremens outgrow enum's and move
into say a std::vector or std::map?


This sounds like it might be a reasonable solution to the OP's problem.
Push all your values into a std::vector and then iterate over the vector
in the comparison function. There may be a really simple solution using
something in <algorithm>.

--
Marcus Kwok
Oct 12 '05 #6
Klaus Schneider wrote:
mlimber wrote:
Using va_arg is very much discouraged in C++ because it is not
typesafe. Mixing it with templates, as the FAQs would say, might be
legal but it certainly ain't moral! What is the problem that
necessitates va_args? Can you do it another way?

Hi!

I want to create a vector with any number of arguments in one call, i.e.
typedef { TEMPERATURE, POTENTIAL, OUTFLOW } DataType;
Vector<DataType> v(4, TEMPERATURE, POTENTIAL, TEMPERATURE, OUTFLOW);

As it might have any number of elements, it's impossible to use overloading.
If there is another solution, I would prefer that, but I couldn't think of
one.

Thanks very much,
Klaus


Hi, Klaus. Please put your responses below the quoted text. Top posting
is considered impolite.

There are several approaches beyond the dreaded elipsis. First, you
might consider the Boost.Assignment library
(http://www.boost.org/libs/assign/doc/). It allows you to write code
like this:

std::vector<int> v;
v += 1,2,3,4,5,6,7,8,9;

Alternately, you can roll your own intialization with method chaining
(cf. http://www.parashift.com/c++-faq-lit...ml#faq-10.18):

#include <vector>
using namespace std;

template<typename T>
class Initializer
{
vector<T> v_;
public:
Initializer& Add( const T& t ) { v_.push_back(t); return *this; }
operator vector<T>() const { return v_; }
};

// Note: no need for typedef for the enum in C++
enum DataType { TEMPERATURE, POTENTIAL, OUTFLOW };

int main()
{
vector<DataType> v = Initializer<DataType>()
.Add( TEMPERATURE )
.Add( POTENTIAL )
.Add( TEMPERATURE )
.Add( OUTFLOW );
// ...
return 0;
}

Cheers! --M

Oct 12 '05 #7
>> Not knowing where you're full code is eventually going,
it may be that you're requiremens outgrow enum's and move
into say a std::vector or std::map?


This sounds like it might be a reasonable solution to the OP's problem.
Push all your values into a std::vector and then iterate over the vector
in the comparison function. There may be a really simple solution using
something in <algorithm>.

It seems you misunderstood what I was trying to do. I have
template <class T>
class Vector : public QValueVector<T>
{
/* just add a new constructor with variable arguments */
};
typedef { TEMPERATURE, POTENTIAL, OUTFLOW } DataType;

I want to have a function
loadData(const char* filename, Vector<DataType> type, Vector<int> indices)
which I want to call as
loadData("experiment.dat",
Vector<DataType>(4,TEMPERATURE, POTENTIAL, TEMPERATURE, OUTFLOW),
Vector<int>(4, 7, 10, 5, 2));

Of course I could do
QValueVector<DataType> types(4);
types.append(TEMPERATURE);
types.append(POTENTIAL);
types.append(OUTFLOW);
types.append(TEMPERATURE);
QValueVector<int> indices(4);
indices.append(7);
indices.append(10);
indices.append(5);
indices.append(2);
loadData(filename, types, indices);

but this is confusing because you don't see the structure of the data
without looking twice. Thus, I thought I'd enhance QValueVector by a new
constructor... but somehow it didn't work as I thought it would.

Do you have suggestions for a "clean" solution to the problem?

Thanks,
Klaus

Oct 12 '05 #8
mlimber wrote:
Klaus Schneider wrote:
mlimber wrote:
> Using va_arg is very much discouraged in C++ because it is not
> typesafe. Mixing it with templates, as the FAQs would say, might be
> legal but it certainly ain't moral! What is the problem that
> necessitates va_args? Can you do it another way?

Hi!

I want to create a vector with any number of arguments in one call, i.e.
typedef { TEMPERATURE, POTENTIAL, OUTFLOW } DataType;
Vector<DataType> v(4, TEMPERATURE, POTENTIAL, TEMPERATURE, OUTFLOW);

As it might have any number of elements, it's impossible to use
overloading. If there is another solution, I would prefer that, but I
couldn't think of one.

Thanks very much,
Klaus


Hi, Klaus. Please put your responses below the quoted text. Top posting
is considered impolite.

There are several approaches beyond the dreaded elipsis. First, you
might consider the Boost.Assignment library
(http://www.boost.org/libs/assign/doc/). It allows you to write code
like this:

std::vector<int> v;
v += 1,2,3,4,5,6,7,8,9;

Alternately, you can roll your own intialization with method chaining
(cf. http://www.parashift.com/c++-faq-lit...ml#faq-10.18):

#include <vector>
using namespace std;

template<typename T>
class Initializer
{
vector<T> v_;
public:
Initializer& Add( const T& t ) { v_.push_back(t); return *this; }
operator vector<T>() const { return v_; }
};

// Note: no need for typedef for the enum in C++
enum DataType { TEMPERATURE, POTENTIAL, OUTFLOW };

int main()
{
vector<DataType> v = Initializer<DataType>()
.Add( TEMPERATURE )
.Add( POTENTIAL )
.Add( TEMPERATURE )
.Add( OUTFLOW );
// ...
return 0;
}


Thanks very much! That is really what I needed...
Klaus

Oct 12 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: gao_bolin | last post by:
I am facing the following scenario: I have a class 'A', that implements some concept C -- but we know this, not because A inherits from a virtual class 'C', but only because a trait tell us so: ...
2
by: Amon Tse | last post by:
I have the following code which is unable to compile in VC6: #include <iostream> template<size_t target, size_t idx = 0> struct _Iterator { enum { value = (target == idx) ? idx :...
1
by: Kai-Uwe Bux | last post by:
Hi folks, I would like to know which clause of the standard rules out this: template < typename eval > struct recursive_template { typedef typename eval::enum_type Enum;
1
by: mathieu | last post by:
Hello there, I am playing around with template metaprograming: I am trying to redefines my own types. But I am facing a small issue, where I cannot describe the whole implementation in one...
5
by: Mark Stijnman | last post by:
I am trying to teach myself template metaprogramming and I have been trying to create lists of related types. I am however stuck when I want to make a template that gives me the last type in a...
6
by: Andre Kempe | last post by:
hej folks. i have a heap with fixed size and want to determine the depth of a element with given index at compile-time. therefore i wrote some templates. however, when i use template...
3
by: desktop | last post by:
When I try to compile this template I get an error in the line: "enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1};" saying: blop.hpp:8: error: expected primary-expression before ‘>’ token...
7
by: Kevin | last post by:
I'm creating a template to support state machines. In doing so, I need to pass an enumeration for the number of transitions and a non type parameter for the range of the enum (to allow me to...
4
by: Alan Woodland | last post by:
I've been trying out more template metaprogramming ideas with typelists (mostly for personal learning, I'm aware boost most probably provides this facility already), and I've run into this small...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.