I'm running these two lines of code to add to a map later on:
o.add("-i", 800, "int option");
o.add("-w", "'switch on' option (no third parameter)");
To add them i'm using my two add functions defined as:
template<class T>
void add(std::string name, T value, std::string desc);
template<class T>
void add(std::string name, std::string desc);
The first one works fine, and returns the values I want, but if I add the second one, I get the error:
error: no matching function for call to ‘Opt::add(const char [3], const char [40])’
My question is why it's using my strings in the first one properly, and my strings in the second are being thought of as const char arrays.
Thank you in advance.
Since you're not using the template argument in your second overload, remove it:
template<class T>
void add(std::string name, T value, std::string desc);
void add(std::string name, std::string desc);
A working sample can be found here.
The error message is weird, but to use the second overload you need to explicitly specify the template argument (since there's no way to automatically deduce it):
o.add<T>("-w", "'switch on' option (no third parameter)");
Or, if you don't actually need the template parameter in this case, just make it a non-template method.
Related
I have a module which receives ASCII commands and then reacts to them accordingly. I am wondering if it is possible, to have a more robust and typesafe way of calling handler functions.
In the past, I had code like the following, which is also very similar to this answer: Processing ASCII commands via RS232 in embedded c
struct Command commands[] = {
{"command1", command1Handler}
{"command2", command2Handler}
...
};
//gets called when a new string has been received
void parseCmd(const char *input) {
//find the fitting command entry and call function pointer
}
bool command1Handler(const char *input) { }
bool command2Handler(const char *input) { }
I don't like that all handler functions have to do their own parsing. This seems needlessly repetitive and error prone.
It would be cool, if instead we could have it the following way, where all parsing is done in the the parseCmd function:
struct Command commands[] = {
{"command1", command1HandlerSafe}
{"command2", command2HandlerSafe}
...
};
void parseCmd(const char *input) {
//1. find fitting command entry
//2. check that parameter number fits the expected number for the target function
//3. parse parameters and validate the types
//4. call function with parameters in their correct types
}
bool command1HandlerSafe(bool param1, const char *param2) { }
bool command2HandlerSafe(int param1) {}
I think with old C-style varargs it would be possible to do the parsing in a central function, but that would not bring type safety.
Edit:
Meanwhile I came up with the following solution, which I thought somewhat balances the hackiness and modularization:
class ParameterSet{
struct Param{
const char *paramString;
bool isInt();
int toInt();
float toFloat();
..
}
ParameterSet(const char *input);
Param at(size_t index);
size_t length();
char m_buffer[100];
Param m_params[10];
}
bool command1HandlerMoreSafe(const ParameterSet *paramSet);
Building an abstraction layer around this might make things more complex and thereby bug prone. I wouldn't do that unless the amount of commands you are supposed to handle is vast, needs to be maintained, and this is one of the main tasks of your application.
With the pre-requisites to keep type safe and keep parsing separate from algorithms, you could build something similar to the following C-like pseudo code:
typedef enum
{
INT,
STR
} type_t; // for marking which type that is supported by the command
typedef struct
{
type_t type;
const char* text; // what kind of text that is expected in case of strings
} arg_t;
typedef struct
{
const char* name; // the name of the command
arg_t* args; // list of allowed arguments
size_t args_n; // size of that list
void (*callback)(void); // placeholder for callback functions of different types
} command_t;
You can then make callback handler functions that aren't concerned about parsing, but only about their dedicated task:
void cmd_branch (const char* str);
void cmd_kill (int n);
The array of commands might look something like this:
const command_t commands[] =
{
{ // BRANCH [FAST][SLOW]
.name="BRANCH",
.args=(entry_t[]){ {STR,"FAST"}, {STR,"SLOW"} },
.args_n=2,
.callback= (void(*)(void)) cmd_branch,
},
{ // KILL [7][9]
.name="KILL",
.args=(entry_t[]){ {INT, NULL} },
.args_n=1,
.callback= (void(*)(void)) cmd_kill,
}
};
The parse function will then do:
Find which command that was received by searching the above list (bsearch if large list).
Check what type of arguments the received command supports
Parse arguments accordingly
Call the relevant function with arguments of the appropriate type
Since this example just used some dummy type function pointer (void(*)(void)), you'll have to cast to the correct type. Can be done by for example C11 _Generic:
call(commands[i], int_val);
which expands to:
#define call(command, arg) _Generic((arg), \
int: (void(*)(int)) command.callback, \
const char*: (void(*)(const char*)) command.callback )(arg)
One way to keep the command handling interfaces the same is to fall back on the venerable argv / argc interface that main() receives. Assuming the received commands have some notion of words (perhaps whitespace separated), it could go like this:
Receive the input string.
Parse the input into words where the first word is the name of the command and the remaining words are its arguments.
As the parsing proceeds, place a pointer to the string that contains each word in an array and keep count of the number of elements in the array.
Using the first word, look up a command function pointer. You can use something like bsearch() if the commands are all known at compile time. Perhaps a hash table might also be appropriate. However you implement the mapping, the result is a pointer to a function that takes an array of pointers to the arguments and a count of the number of elements in the pointer array.
Invoke the command function via its pointer and pass the array of parsed words and the count, just like main() is invoked by startup code.
From there, each command function can deal with what its arguments specifically mean, converting strings representations to internal forms as necessary.
Suppose we have a template:
template <class T>
void VeryImportantFunction(T t) {
// something
}
Somewhere it is called with something like:
// ..
int a = 12345;
VeryImportantFunction(a);
// ..
It is very big project with tons of source code, and occasionally somewhere in deep of the code appears a new header with overloaded function:
void VeryImportantFunction(int t) {
// totally another behavior
}
And code fragment above will call overloaded function, because it have more priority.
Can we somehow disable or in another way compile-time detect functions that can overload our important template?
Your question is unclear, but here's my take on it.
If you want to hit the template overload, you can simply invoke the function by explicitly specifying the template parameters:
int a = 12345;
VeryImportantFunction<int>(a);
If you want this from happening again in the future, then make VeryImportantFunction either a lambda or a struct - those cannot be overloaded "externally":
inline const auto VeryImportantFunction = [](auto x){ /* ... */ };
// no one can overload this!
If you want to know all the overloads of VeryImportantFunction without external tooling, then call it in a completely wrong way - the compiler error will likely show all considered overloads:
VeryImportantFunction(5, 5, 5, 5);
// error... will likely show all candidates
Write
inline void VeryImportantFunction(int t)
{
VeryImportantFunction<int>(t); // call the template function
}
immediately after your template definition.
Then if someone has written their own version of void VeryImportantFunction(int t), you'll get a compiler error.
I created a function like:
void triangle(int n, int start=1, int spcs=0, char dec_y='n', char lf='#',char decf='o') {
//some code
}
I wanted to know is there any way that I could call this function like this:
triangle(9, dec_y='y', lf='&');
without doing this:
void triangle2(int nn, char d_ec_y, char llf) {
triangle(nn, 1, 0, d_ec_y, llf, 'o');
}
// then in main simply
triangle2(9, 'y', '&');
You can't change the order of the parameters. So you can't do what you want directly. You have three options:
One that you don't want to.
You can pass the parameters as structure. The struct can have default values. And you can only alter the ones which you want before calling the function.
For example:
struct params
{
params(int n_)
:n(n_)
{
}
int start=1;
int spcs=0;
char dec_y='n';
char lf='#';
char decf='o';
};
...
params p(0);
p.dec_y='y';
p.lf='&';
triangle(p);
You can use boost::parameter which provides exactly what you want. Check this question for a sample usage.
No, c++ requires that any parameters for which the default parameter will be used come after all specified parameters.
In some circumstances this can be worked around by having multiple overloads. But due to argument ambiguity that is not always possible. The idea is to leave out some of the middle arguments, as in:
void foo(int, char const *, int =0);
void foo(int, int=0);
This pair always requires the first int but allows that to be followed by either a string or another int, and if the string version is used still allows the final int argument.
Using some advanced meta-programming it is actually possible to make all the arguments optional and to supply them in any order without declaring any overloads. For example this is implemented in boost.process API:
namespace bp = ::boost::process;
bp::environment env{::boost::this_process::environment()};
bp::child ch0("cmd", env); // ok
bp::child ch1("cmd", env, bp::windows::hide); // fine too
bp::child ch2("cmd", bp::windows::hide, env); // still fine
bp::child ch3("cmd", bp::windows::hide); // no problem
The idea behind this is that each supported argument is wrapped into a trait class that supplies manipulation method(s) and all those calls invoke the same template function which invokes manipulation method for each supplied argument.
Let's say I want to have a function overloaded by two versions like this:
a) void query(const string& s); which makes an SQL query to a server.
b) void query(const string& s,...); which builds a query string given by a format string and arguments to be substituted. Internally, this version looks like (I hide the details to not over-complicate the question):
va_list vargs;
va_start(vargs, s);
// ... call vsnprintf to build the query string
// ... call the first version with the query string
va_end(vargs);
Note that I also want this to work in both MSVC and GCC. Of course, by writing as above, I cannot go for the following call because of ambiguity:
query("...");
To resolve the ambiguity in this case, I have tried several ways, but none of them works:
1) Rewrite them as:
void query(const string& s) {
// ...
}
template<typename Value>
void query(const string& s, Value value,...) {
va_list vargs;
va_start(vargs, s);
// ...
}
This compiles and works fine in MSVC, but GCC complains with a warning:
"second parameter of va_start is not last named argument"
Even if I ignore that warning, it doesn't work. Somehow vargs cannot capture value parameter for whatever I try: va_start(vargs, s) or va_start(vargs, value). It seems to me that GCC always takes only unnamed parameters into vargs no matter what we provide as 2nd parameter to va_start.
2) Rewrite them as
void query(const string& s) {
// ...
}
template<typename... Values>
enable_if<(sizeof...(Values) > 0), void>::type
query(const string& s, Values value...) {
va_list vargs;
va_start(vargs, s);
// ...
}
Again, this compiles and works with MSVC. But GCC complains with an error that the 2nd version is a variadic template rather than variadic function, and va_start is not allowed to be used there. It seems that va_start in GCC is built-in rather than from library.
Some people can remark that actually in the 2 versions, 2nd version supersedes the 1st one. That means if I remove the 1st version and put it internally into the 2nd, then everything is alright. But I have a good reason to keep the 1st version: I want the calls with just a string to go directly without unneccessarily calling vsnprintf. So please do not suggest me this way.
I have also thought about combining the 1st version into the 2nd, and then internally count the number of given arguments to know how to go. But it doesn't seem to have a standard way to do that. Determining the number of arguments is possible with variadic templates but not with variadic functions. And if I switch into variadic template, I cannot use va_start anymore in GCC.
Hope someone can help!!
I haven't tested this, but wouldn't the following work?
void query_varargs(const string &s, ...) {
va_list vargs;
va_start(vargs, s);
// ...
}
template<typename... Values>
enable_if<(sizeof...(Values) > 0), void>::type
query(const string& s, Values value...) {
query_varargs(s, ...value);
}
I.e. move the functionality into a different function (query_varargs), then have the variadic template version of query forward to it.
I'm getting some errors when using strcpy_s and can't figure out what I'm doing wrong.
The code:
Player.hpp:
string name;
Player(string);
Player.cpp:
Player::Player(string newName)
{
strcpy_s(name, name.size(), newName);//error is here
health = 20;
}
The errors:
Too many arguments in function call
No instance of overloaded function 'strcpy_s' matches the argument list
You cannot use strcpy_s to copy std::string. Actually, you just need to do:
Player::Player(string newName) {
name = newName;
health = 20;
}
Even better, you could use a constructor initialization list:
Player::Player(string newName) : name(newName), health(20) {}
As a reference, here you have a detailed description of std::string class.
This URL states that the C++ version only uses template overloaded
functions (2 arguments not 3):
http://msdn.microsoft.com/en-us/library/td1esda9%28v=vs.80%29.aspx
template
errno_t strcpy_s(
char (&strDestination)[size],
const char *strSource
); // C++ only
According to this URL:
In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. For more information, see Secure Template Overloads.
(As stated in the prototype this function is for char* arguments - not for string data types)