how to use strcat with an ENUM? - c++

I have an external tool which is generating an ENUM based on user inputs. Now this ENUM is being used by my C++ code where in i have to select a particular ENUM based on a variable say 'x'. The ENUMS generated are of the form 'ENUM_1', 'ENUM_2', 'ENUM_3'....so on. Now I want the code inside my code such that the appropriate ENUM is chosen based on 'x'. I tried using the strcat function like:
typedef enum ( enum_1, enum_2, enum_3...enum_n) map1;
y=(map1)strcat("enum_", x);
but it gives me the error "Cannot convert from char* to map1.
Can someone pls suggest a method of achieving this.
ThankYou

You can't do this using strcat. From the description what I understand is that you want to convert x to map1. To achieve this, you can do map1 m = (map1)(x-1); See this sample code:
typedef enum { enum_1, enum_2, enum_3} map1;
int main()
{
int x = 1;
map1 m = (map1)(x-1);
}
-1 is required because, the integer value of the enums in map1 starts from 0.

You can't do this. Well you can't do it this way...
Enums aren't evaluated by name at compile time. You'll have to try something with the preprocessor. You can create a define to do something similar. Something like:
#define fn(x) enum_##x
And then call
fn(x)
But this happens when the file gets preprocessed. So you can't access runtime variables. Judging by your code I don't think you'll be able to do what you want.
Good luck though.

Now I want the code inside my code such that the appropriate ENUM is chosen based on 'x'.
Enumerated values are constants and based on the statement I assume that x is an integer data type.
y=(map1)strcat("enum_", x);
strcat(..) passing parameters should be of type char*. And clearly x is not of type char* based on previous statement. It not clear why are you using strcat for achieving this task.
Answer for your subject line: No. You cannot use strcat with enumerated values.

Related

Is there a non-hacky way in libfmt to construct names for named arguments at runtime?

I am using libfmt to build a code generator that generates a sort of adapter layer around an existing library. So I have a dataset of parameter descriptions that include format strings describing the conversion from the data type in the outer layer to the data type in the inner layer. In the most simple case, this might look like
"{type_out} {var_out} = {var_in};\n"
in a more complex case, the conversion might depend on another parameter:
"int {var_out} = function_call({var_in}, {dependent_param__var_out});\n"
The name dependent_param (and as such any name that refers to one of its attributes, such as dependent_param__var_out) is not known to the code generator at compile time; it's constructed at runtime from the parameter dataset.
This means that I need to build a fmt::dynamic_format_arg_store some of whose named arguments are constructed at runtime. In essence, what I would like is along the lines of
#include <fmt/args.h>
#include <fmt/format.h>
#include <string>
fmt::dynamic_format_arg_store<fmt::format_context>
construct_arg_store(std::string const &paramname) {
fmt::dynamic_format_arg_store<fmt::format_context> fmt_args;
// so far, so good.
fmt_args.push_back(fmt::arg("var_in", paramname));
fmt_args.push_back(fmt::arg("var_out", paramname + "_out"));
// imagine this were constructed by iterating over runtime-available data.
std::string argname = "dependent_param__var_out";
std::string argvalue = "dependent_param_out";
// Does not compile; fmt::arg expects char const *
fmt_args.push_back(fmt::arg(argname, argvalue));
return fmt_args;
}
int main() {
std::string fmtstring = "int {var_out} = function_call({var_in}, {dependent_param__var_out});\n";
auto args = construct_arg_store("foo");
fmt::vprint(fmtstring, args);
}
Right now, I build a symbol table from the dataset that contains std::string objects for all possible format arg names and use their .c_str() to build the fmt::arg objects (so that the generated C strings have a long enough lifetime). This works, but it seems like a bit of a dirty hack.
So I'm wondering, is there a better way to do it than that?
In general, it's better to use a template system like Mustache for this. That said, storing argument names as std::strings on the side and use them to construct dynamic_format_arg_store is OK. There is nothing hacky about it.

Indeterminate return type of a function

I'm developing a parser of Adobe Type 1 font, using C++ language. And there is a problem when I tried to decode the DICT Data.
The operands in the DICT, which are stored as byte-sequence in the PDF file, may be either integer or real number.
I defined a function, whose prototype is getOperandVal(unsigned char* buf), to decode the sequence to number. And the problem appeared.
Before parse the buf, we can not know the buf is real or integer number. So I can not determine the return-value type, which should be int or double.
A solution is to use a struct as the return-value type. The struct is like below:
typedef struct
{
int interger;
double real;
bool bReal;
}RET;
Then the function prototype is:
RET getOperandVal(unsigned char* buf);
But I think it is not compact. First of all, it is inconvenient to use. Second, the program will run slower when the size of data is big.
Can anyone give me a better solution? Can template do it?
Thank you very much!
Addition:
The program will transfer the operands value into byte-sequence for rewriting into file after edit. Consider the requirement, please.
You can't use templates because you don't know at compile time what type will be returned.
But you can use a union:
struct Int_real {
union {
int integer;
double real;
};
bool is_real;
};
A very good idea is to improve upon it by making it safe (allow access to only the field of the union that is active).
Pretty soon (hopefully), you will be able to use std::any
Template types are evaluated at the compile time, you could not change function prototype dynamically. You could either upscale return value to the biggest size (for example always return double), return a struct or use some variant implementation, like boost::variant.

Accessing the values of an enum defined in a struct

The struct is as follows:
struct padData
{
enum buttonsAndAxes
{
select,
start,
ps
};
};
The object of the struct:
padData pad;
I am accessing this enum as follows:
printf ("\n%d", pad.buttonsAndAxes[0]);
Error:
error: invalid use of ‘enum padData::buttonsAndAxes’
Then, I tried:
printf ("\n%d", pad::buttonsAndAxes[0]);
Error:
error: ‘pad’ is not a class or namespace
Now what? Please guide.
Compiler: gcc version 4.5.0
EDIT 1:____________________________________
printf ("\nemit: %d", padData::(select)0);
results in:
error: expected unqualified-id before ‘(’ token
My aim is to fetch the word "select" through its value 0. How to achieve that? Also, is the word "select" a string?
The enum values become names in the scope of the class. So you would use padData::select from outside the class, or just select from inside the class.
In C++11 you can qualify the enumerators with the name of the enum, giving padData::buttonsAndAxes::select from the outside and buttonsAndAxes::select from inside.
Printing the name of an enumerator is not easily done in C++, because the names are gone after compilation. You need to set up a table mapping the values to their strings by hand. If you don't supply explicit values like in your example, you can simply use an array:
enum buttonsAndAxes
{
select,
start,
ps
};
const char* buttonsAndAxesNames[] = {
"select",
"start",
"ps"
};
And then you index into that array:
printf("%s", buttonsAndAxesNames[select]);
If you want some more sophisticated approach, you can find a bunch of tricks in previous questions.
printf ("\n%d", padData::select);
Enum is not array, it is used without index.
ENUMS are mainly used for better readability of code rather than calculation facilitators. ENUMS are mainly literals which are assigned values 0,1,2 etc unless specified otherwise. So you should always use them with "::" qualification rather than as array
You seem to need a good C++ book.
Enumerations, in C and C++, are a convenient way to:
map an integral value to a "smart" name
group together values that belong together
The syntax is quite simple (in C++03):
enum <enum-name> {
<value-name-0> [= <value-0>],
<value-name-1> [= <value-1>],
...
};
Where:
<enum-name> is the name of the type that is introduced
<value-name-X> is the name of a value of the enum
<value-X> is the value given to the name, and is optional
If no value is given to a name:
if it is the first, it is set to 0
else, it is set to the value of the previous name, + 1
Here is a small example demonstrating the use of enums:
enum Color {
Blue,
Green,
Red
};
char const* name(Color c) {
switch(c) {
case Blue: return "Blue";
case Green: return "Green";
case Red: return "Red";
}
assert(0 && "Who stored crap in my enum ?");
}
This illustrates a few important points at once:
Color is a type, like a struct type or a class type. It can be typedefed and all.
an enum "value-name" is an integral constant, it can be used as template parameter or in switch cases.
an enum "value-name" is injected in the scope in which the type is declared, and not nested within. (C++11 allows to scope the values with the enum class syntax)
something else entirely could be stored in the enum, while this should not happen in well behaved applications, you can do it through casting...
What is not shown, is that an enum is under the hood a plain integer. The exact underlying type though is determined at the discretion of the compiler. There are a few rules in this choice, that should not matter to you, all you should know is that the type chosen is wide enough to contain all the values of the enum (and possibly signed if required). What it implies is that the type chosen is not necessarily a plain int.
Therefore: printf("%d", Green); is a programming error. It should be printf("%d", (int)Green);.
Another important point, is that enum names do not appear in the final binary. The names are substituted for their values directly, no runtime overhead at all. Debuggers typically retrieve the names from the debug information (if available) and substitute them back in when presenting the information to you.

error when declaring an enum to a variable

I have the following syntax:
enum home
{
no,
yes,
}homew;
home homes;
std::string s;
s="no";
homes=s; //is not working. Why?
Were am I wrong?
You are confusing strings with enumerated values.
An enum variable is simply an integer that you can use a literal for at compile time, nothing more than that.
It makes the code more understandable and self-documenting rather than merely using a number literal.
This
enum home { no, yes, } homew;
defines the type home plus a variable homew of that type.
Did you intent that? Why?
The values defined for an enum type are literals, to be used as such:
home homes = no;
In C++ there's no built-in way to convert between enum value literals and a string representation of them. If you need this, you'll have to cook up your own.
enums in C++ are implicitly an int data type. You can't assign string values to enum.
It doesn't compile because C++ provides no built-in mechanism for converting from std::string to an enum.
typeof(home) != typeof(std::string) // types are not equal
Thus, you cannot assign an enum to std::string or otherwise. Implicit conversion between enum and integral types like bool, int etc. is possible however.
Is there a way I can solve my problem as it is?
If possible use std::map.
std::map<std::string, home> myTypes;
myTypes["yes"] = yes;
myTypes["no"] = no;
Now you can do,
homes = myTypes["no"];
As others pointed out, enums values are of int type. You could instead write a small function that converts from enum to String like this:
std::string GetStringFromEnum(home iHome)
{
switch (home)
{
case yes: return "yes";
case no: return "no"; break;
default: return "here be dragons";
}
}
and vice-versa:
home GetEnumFromString(std::string iImput)
{
if (iImput == "yes") return yes;
return no; //if you extend the enum beyond 2 values, this function will get more complicated
}
and you could modify your code like so:
homes = GetStringFromEnum(no)
the downside for this approach is that if you modify the enum, you must also modify the convert function.
HTH,JP

Help using MFC CMap (or std::map) please

a C++ noob here. I am trying to tweak some code, with the following key lines (meaning they are not the only ones, but they are the only ones that should matter for this question). By the way, I am using Visual Studio 2010 C++ compiler on Windows.
CMap<ATL::CAtlString,LPCTSTR,UINT,UINT> mapForDuplicates; // "dict" definition
ATL::CAtlString strDescription = ... // let's just say it gets set to a value.
UINT nFound = 0; // What is this for???
BOOL bFound = mapForDuplicates.Lookup(strDescription, nFound);
mapForDuplicates[strDescription] = 1;
Now ... I really do not want to use the UINT here, as bool is all I really need. However, I could not figure out what all of the arguments for the CMap constructor really are. When using C#, all I have to specify is the type of the key and the type of the value. The fact that ATL::CAtlString does not match LPCSTR really confuses me. What exactly are KEY, ARG_KEY, VALUE, and ARG_VALUE? Why do I need all four and can all four be different? Thanks.
...
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
class CMap : public CObject
...
Note: I could use std::map here instead(although I have not used it either); the only non-negotiable is ATL::CAtlString - I have to use this type. Let me know if you have questions.
IIRC the four args to the template are there so you can throw one type in and get another (const) type back. Here it throws in CAtlStrings, but it'll get back LPCTSTR. Often you just specify the same to types twice (e.g. int, int, float, float for a map of ints -> floats).
Grr, that extra L really irks me nowadays, it was great for 16-bit Windows but nowadays... PCSTR is all that's needed. 'L' is the useless appendix of Windows programming.
nFound is something coming out of the map, the map maps to UINT so nFound is a UINT.
Start with the docs for the class =- there is a ref to a sample here too
http://msdn.microsoft.com/en-us/library/s897094z(VS.71).aspx
By the way, the following pseudo-sample did the trick for me.
std::set<CAtlString> setOfDescriptions;
for each(...)
{
CAtlString strDescription = GetDescription();
if (setOfDescriptions.find(strDescription) != setOfDescriptions.end())
{
// Remove a duplicate.
}
setOfDescriptions.insert(strDescription); // Mark as seen.
}