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.
}
Related
I'm reading the documentation of std::experimental::optional and I have a good idea about what it does, but I don't understand when I should use it or how I should use it. The site doesn't contain any examples as of yet which leaves it harder for me to grasp the true concept of this object. When is std::optional a good choice to use, and how does it compensate for what was not found in the previous Standard (C++11).
The simplest example I can think of:
std::optional<int> try_parse_int(std::string s)
{
//try to parse an int from the given string,
//and return "nothing" if you fail
}
The same thing might be accomplished with a reference argument instead (as in the following signature), but using std::optional makes the signature and usage nicer.
bool try_parse_int(std::string s, int& i);
Another way that this could be done is especially bad:
int* try_parse_int(std::string s); //return nullptr if fail
This requires dynamic memory allocation, worrying about ownership, etc. - always prefer one of the other two signatures above.
Another example:
class Contact
{
std::optional<std::string> home_phone;
std::optional<std::string> work_phone;
std::optional<std::string> mobile_phone;
};
This is extremely preferable to instead having something like a std::unique_ptr<std::string> for each phone number! std::optional gives you data locality, which is great for performance.
Another example:
template<typename Key, typename Value>
class Lookup
{
std::optional<Value> get(Key key);
};
If the lookup doesn't have a certain key in it, then we can simply return "no value."
I can use it like this:
Lookup<std::string, std::string> location_lookup;
std::string location = location_lookup.get("waldo").value_or("unknown");
Another example:
std::vector<std::pair<std::string, double>> search(
std::string query,
std::optional<int> max_count,
std::optional<double> min_match_score);
This makes a lot more sense than, say, having four function overloads that take every possible combination of max_count (or not) and min_match_score (or not)!
It also eliminates the accursed "Pass -1 for max_count if you don't want a limit" or "Pass std::numeric_limits<double>::min() for min_match_score if you don't want a minimum score"!
Another example:
std::optional<int> find_in_string(std::string s, std::string query);
If the query string isn't in s, I want "no int" -- not whatever special value someone decided to use for this purpose (-1?).
For additional examples, you could look at the boost::optional documentation. boost::optional and std::optional will basically be identical in terms of behavior and usage.
An example is quoted from New adopted paper: N3672, std::optional:
optional<int> str2int(string); // converts int to string if possible
int get_int_from_user()
{
string s;
for (;;) {
cin >> s;
optional<int> o = str2int(s); // 'o' may or may not contain an int
if (o) { // does optional contain a value?
return *o; // use the value
}
}
}
but I don't understand when I should use it or how I should use it.
Consider when you are writing an API and you want to express that "not having a return" value is not an error. For example, you need to read data from a socket, and when a data block is complete, you parse it and return it:
class YourBlock { /* block header, format, whatever else */ };
std::optional<YourBlock> cache_and_get_block(
some_socket_object& socket);
If the appended data completed a parsable block, you can process it; otherwise, keep reading and appending data:
void your_client_code(some_socket_object& socket)
{
char raw_data[1024]; // max 1024 bytes of raw data (for example)
while(socket.read(raw_data, 1024))
{
if(auto block = cache_and_get_block(raw_data))
{
// process *block here
// then return or break
}
// else [ no error; just keep reading and appending ]
}
}
Edit: regarding the rest of your questions:
When is std::optional a good choice to use
When you compute a value and need to return it, it makes for better semantics to return by value than to take a reference to an output value (that may not be generated).
When you want to ensure that client code has to check the output value (whoever writes the client code may not check for error - if you attempt to use an un-initialized pointer you get a core dump; if you attempt to use an un-initialized std::optional, you get a catch-able exception).
[...] and how does it compensate for what was not found in the previous Standard (C++11).
Previous to C++11, you had to use a different interface for "functions that may not return a value" - either return by pointer and check for NULL, or accept an output parameter and return an error/result code for "not available".
Both impose extra effort and attention from the client implementer to get it right and both are a source of confusion (the first pushing the client implementer to think of an operation as an allocation and requiring client code to implement pointer-handling logic and the second allowing client code to get away with using invalid/uninitialized values).
std::optional nicely takes care of the problems arising with previous solutions.
I often use optionals to represent optional data pulled from configuration files, that is to say where that data (such as with an expected, yet not necessary, element within an XML document) is optionally provided, so that I can explicitly and clearly show if the data was actually present in the XML document. Especially when the data can have a "not set" state, versus an "empty" and a "set" state (fuzzy logic). With an optional, set and not set is clear, also empty would be clear with the value of 0 or null.
This can show how the value of "not set" is not equivalent to "empty". In concept, a pointer to an int (int * p) can show this, where a null (p == 0) is not set, a value of 0 (*p == 0) is set and empty, and any other value (*p <> 0) is set to a value.
For a practical example, I have a piece of geometry pulled from an XML document that had a value called render flags, where the geometry can either override the render flags (set), disable the render flags (set to 0), or simply not affect the render flags (not set), an optional would be a clear way to represent this.
Clearly a pointer to an int, in this example, can accomplish the goal, or better, a share pointer as it can offer cleaner implementation, however, I would argue it's about code clarity in this case. Is a null always a "not set"? With a pointer, it is not clear, as null literally means not allocated or created, though it could, yet might not necessarily mean "not set". It is worth pointing out that a pointer must be released, and in good practice set to 0, however, like with a shared pointer, an optional doesn't require explicit cleanup, so there isn't a concern of mixing up the cleanup with the optional having not been set.
I believe it's about code clarity. Clarity reduces the cost of code maintenance, and development. A clear understanding of code intention is incredibly valuable.
Use of a pointer to represent this would require overloading the concept of the pointer. To represent "null" as "not set", typically you might see one or more comments through code to explain this intention. That's not a bad solution instead of an optional, however, I always opt for implicit implementation rather than explicit comments, as comments are not enforceable (such as by compilation). Examples of these implicit items for development (those articles in development that are provided purely to enforce intention) include the various C++ style casts, "const" (especially on member functions), and the "bool" type, to name a few. Arguably you don't really need these code features, so long as everyone obeys intentions or comments.
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.
I'm currently working on a DLL that needs to convert back and forth between the friendly name for a value and the value itself. As this code is used in many places throughout the codebase, I want to try and keep it simple and in a single function or object so I only have to declare them once.
From my reading it looks like CMap is the tool for the job, but I can't seem to discover any combination of template arguments that compiles without errors.
My values are CString and int. I tried the following definition:
CMap<int, int, CString, CString> encodermap;
which compiles, but when I try to add a value:
encodermap["Encoder 1"] = 0;
I get the following compiler errors:
error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2501: 'encodermap' : missing storage-class or type specifiers
error C2040: 'encodermap' : 'int []' differs in levels of indirection from 'CMap<KEY,ARG_KEY,VALUE,ARG_VALUE>'
I've tried changing the CMap to this:
CMap<CString, CString, int, int> encodermap;
but I get the same four errors.
I'm sure I must be missing something but I'm at a loss as to what.
Because of the SDK being used for this work I'm require VS2003
The problem
I think you've inverted the key type and the valye type.
Your original declaration defines int as being the key to be searched for with operator[]. So encodermap[0] = "Encoder 1"; would work.
But when your compiler sees encodermap["Encoder 1"] = 0;, he tries to find an operator[] which takes char* (or something to which char * can be converted to) and returns an int. The last error message tells you that he couldn't find such an operator for your map.
With MSVC 2015, the error message is more concise: C2679.
The solution
You should define your CMap with a CString key and an int value. The trick to know, is that for a CString KEY, the the ARG_KEY should be LPCWSTR . So the right definition would be:
CMap<CString, LPCWSTR, int, int> encodermap;
This permits to use CString as key in the map's operator[].
Now if you use MFC on windows, you probably use UNICODE and wide chars (therefore the LPCWSTR instead of LPCSTR). When calling the operator you then have either to use a CString or a wide literal:
encodermap[L"Encoder 1"] = 0;
encodermap[CString("Encoder 2")] = 1;
Try this:
CMap<CString, LPCTSTR, int, int> encodermap;
This CodeProject article CMap How-to may be of some help.
Many people get confused about CMap's declaration CMap < KEY, ARG_KEY,
VALUE, ARG_VALUE >, why not just CMap < KEY, VALUE >?
In fact, the ultimate data container in CMap is CPair, and the
internal of CPair is {KEY, VALUE}. Therefore, CMap will really store a
KEY, and not ARG_KEY. However, if you check with the MFC source code,
almost all the internal parameters passing within CMap itself is
called with ARG_KEY and ARG_VALUE, therefore, using KEY & as ARG_KEY
seems always a correct thing, except when:
You are using primitive date types like int, char, where pass-by-value makes no difference (may be even faster) with
pass-by-reference.
If you use CString as KEY, you should use LPCTSTR as ARG_KEY and not CString &, we will talk more about this later.
Edit: Cristophe, another option for the assignment is encodermap[_T("Encoder 1")] = 0;, which will work for single-byte, multi-byte or Unicode with the LPCTSTR typedef. You will also need to #include <tchar.h>.
I have a function with following signature
char requestApiCall(int num, const wchar_t* pParams = 0, ...)
{
...
}
Now I want to to get all pParams in an array (or to be able to iterate over it). I know this is possible with some macros, but I have no idea how to do it.
Any help would be appreciated.
P.S. I'm using MinGW if it matters.
UPDATE
my question caused confusion. I will try to clarify (sorry for my grammar). Both Object Pascal and C# has the ability to pass unlimited amount of parameters to a method. In C# we achieve this with params keyword:
void Foo(params string[] strs)
{
...
}
Foo("first", "second", "another one", "etc");
I want to achieve same result in C++ without using any object/class. In my case, type safety is not a concern, but if there is a type safe way to achieve that goal, I will gladly hear your comments :)
Thanks
You need to look at the functions and macros declared in stdarg.h. Here is a tutorial that explains it.
http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html
I'm not sure what your function parameters are supposed to represent but I think you'll find that it needs to change.
By the way, I find that for C++ I can usually avoid variadic functions. This has the advantage of preserving type safety. Are you sure you really need a variadic function?
Using variadic function arguments is a dangerous and tricky business, and almost surely there is a better way - for example, you might pass an std::vector<std::wstring>& to your function!
OK, that said, here's how to use variadic arguments. The key point is that it is your responsibility to know the number and types of the arguments!
#include <cstdarg>
char requestApiCall(int num, const wchar_t* pParams, ...)
{
va_list ap; // the argument pointer
va_start(ap, pParams); // initialize it with the right-most named parameter
/** Perform magic -- YOU have to know how many arguments you are getting! **/
int a = va_arg(ap, int); // extract one int
double d = va_arg(ap, double) // one double
char * s = va_arg(ap, char*) // one char*
/* ... and so forth ... */
va_end(ap); // all done, clean up
}
Just for completeness, I would redefine the function as this:
char requestApiCall(std::vector<std::wstring> & params)
{
for (std::vector<std::wstring>::const_iterator it = params.begin(), end = params.end(); it != end; ++it)
{
// do something with *it
}
/* ... */
}
A good example of what you are trying to accomplish is the exec family of functions. exec() takes an variable list of arguments all of which are expected to be const char*. The last item is a NULL ((char*)0). The last item is the indicator for when the list of items is complete.
You can use the variadic macros in stdargs.h as others have described.
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.