I have designed a parameter class which allows me to write code like this:
//define parameter
typedef basic_config_param<std::string> name;
void test(config_param param) {
if(param.has<name>()) { //by name
cout << "Your name is: " << param.get<name>() << endl;
}
unsigned long & n = param<ref<unsigned long> >(); //by type
if(param.get<value<bool> >(true)) { //return true if not found
++n;
}
}
unsigned long num = 0;
test(( name("Special :-)"), ref<unsigned long>(num) )); //easy to add a number parameter
cout << "Number is: " << num; //prints 1
The performance of the class is pretty fast: everything is just a reference on the stack. And to save all the information I use an internal buffer of up to 5 arguments before it goes to heap allocation to decrease the size of every single object, but this can be easily changed.
Why isn't this syntax used more often, overloading operator,() to implement named parameters? Is it because of the potential performance penalty?
One other way is to use the named idiom:
object.name("my name").ref(num); //every object method returns a reference to itself, allow object chaining.
But, for me, overloading operator,() looks much more "modern" C++, as long you don't forget to uses double parentheses. The performance does not suffer much either, even if it is slower than a normal function, so is it negligible in most cases.
I am probably not the first one to come up with a solution like this, but why isn't it more common? I have never seen anything like the syntax above (my example) before I wrote a class which accepts it, but for me looks it perfect.
My question is why this syntax is not used more, overloading operator,() to implement named parameters.
Because it is counter-intuitive, non-human-readable, and arguably a bad programming practice. Unless you want to sabotage the codebase, avoid doing that.
test(( name("Special :-)"), ref<unsigned long>(num) ));
Let's say I see this code fragment for the first time. My thought process goes like this:
At a first glance it looks like an example of "the most vexing parse" because you use double-parentheses. So I assume that test is a variable, and have to wonder if you forgot to write variable's type. Then it occurs to me that this thing actually compiles. After that I have to wonder if this is an instance of an immediately destroyed class of type test and you use lowercase names for all class types.
Then I discover it is actually a function call. Great.
The code fragment now looks like a function call with two arguments.
Now it becomes obvious to me that this can't be a function call with two arguments, because you used double parentheses.
So, NOW I have to figure what the heck is going on within ().
I remember that there is a comma operator (which I haven't ever seen in real C++ code during the last 5 years) which discards the previous argument. SO NOW I have to wonder what is that useful side effect of name(), and what the name() is - a function call or a type (because you don't use uppercase/lowercase letters to distinguish between class/function (i.e. Test is a class, but test is a function), and you don't have C prefixes).
After looking up name in the source code, I discover that it is class. And that it overloads the , operator, so it actually doesn't discard the first argument anymore.
See how much time is wasted here? Frankly, writing something like that can get you into trouble, because you use language features to make your code look like something that is different from what your code actually does (you make a function call with one argument look like it has two arguments or that it is a variadic function). Which is a bad programming practice that is roughly equivalent to overloading operator+ to perform substractions instead of additions.
Now, let's consider a QString example.
QString status = QString("Processing file %1 of %2: %3").arg(i).arg(total).arg(fileName);
Let's say I see it for the first time in my life. That's how my thought process goes:
There is a variable status of type QString.
It is initialized from a temporary variable of type QString().
... after QString::arg method is called. (I know it is a method).
I look up .arg in the documentation to see what it does, and discover that it replaces %1-style entries and returns QString&. So the chain of .arg() calls instantly makes sense. Please note that something like QString::arg can be templated, and you'll be able to call it for different argument types without manually specifying the type of argument in <>.
That code fragment now makes sense, so I move on to another fragment.
looks very more "modern" C++
"New and shiny" sometimes means "buggy and broken" (slackware linux was built on a somewhat similar idea). It is irrelevant if your code looks modern. It should be human-readable, it should do what it is intended to do, and you should waste the minimum possible amount of time in writing it. I.e. you should (personal recommendation) aim to "implement a maximum amount of functionality in a minimum amount of time at a minimum cost (includes maintenance)", but receive the maximum reward for doing it. Also it makes sense to follow KISS principle.
Your "modern" syntax does not reduce development cost, does not reduce development time, and increases maintenance cost (counter-intuitive). As a result, this syntax should be avoided.
There is not necessity. Your dynamic dispatch (behave differently, depending on the logical type of the argument) can be implemented a) much easier and b) much faster using template specialisation.
And if you actually require a distinction based on information that is only available on runtime, I'd try to move your test function to be a virtual method of the param type and simply use dynamic binding (that's what it's for, and that's what you're kind of reinventing).
The only cases where this approach would be more useful may be multiple-dispatch scenarios, where you want to reduce code and can find some similarity patterns.
Related
Right now, I am trying to call a function in C++ through a Json object. The Json object would provide me with the name of the callee function and all the parameters. I will be able to extract the parameters using a for loop, but I am not sure how I can pass them in. For loop only allows me to pass arguments one by one, and I did not find a way to call a function besides passing in all the arguments at once.
I've made a temporary solution of:
if (parameter_count == 1)
func(param_1);
if (parameter_count == 2)
func(param_1, param_2);
...
This solution seems would not work for all cases since it can only work for functions with a limited number of arguments (depending on how many ifs I write). Is there a better way for this? Thanks!
EDIT: Sorry if I was being unclear. I do not know anything about func. I will be reading func from DLL based on its string name. Since I can't really change the function itself, I wouldn't be able to pass in a vector or struct directly.
Or perhaps did I have the wrong understanding? Are we allowed to pass in a single vector in place of a lot of parameters?
Sorry for making a mess through so many edits on this question. Brandon's solution with libffi works. Thanks!
So the problem as I understand it is that you have a void * pointer (which would come from your platform's DLL loading code) which "secretly" is a pointer to a function with a signature which is only known at runtime. You'd like to call this function at runtime with specified arguments.
Unfortunately, this is not possible to do cleanly with standard C++ alone. C++ cannot work with types that are not present in the program at compile-time, and since there is an infinite number of potential function signatures involved here there is no way to compile them all in.
What you'll want to do instead is manually set up the stack frame on your call stack and then jump to it, either via inline assembly or via some library or compiler extension that accomplishes this for your platform.
Here is a simple example of doing this via inline assembly. (To do this in general you will need to learn your platform's calling convention in detail, and needless to say this will constrain your program to the platform(s) you've implemented this for.)
I haven't actually tried it, but gcc has a compiler extension __builtin_apply that is apparently just meant to forward the arguments from one method wholesale to another but which could perhaps be used to accomplish something like this if you learned the (apparently opaque) description of the method.
[Update: Apparently I missed this in the comments, but Brandon mentioned libffi, a library which implements a bunch of platforms' calling conventions. This sounds like it might be the best option if you want to take this sort of approach.]
A final option would be to constrain the allowed signatures of your functions to a specified list, e.g. something like
switch(mySignature)
{
case VOID_VOID:
dynamic_cast<std::function<void(void)> *>(myPtr)();
break;
case VOID_INT:
dynamic_cast<std::function<void(int)> *>(myPtr)(my_int_arg_1);
break;
// ...
}
(Syntax of the above may not be 100% correct; I haven't tested it yet.) Whether this approach is sensible for your purposes depends on what you're doing.
I wonder if there is a reason why the std::sto series (e.g. std::stoi, std::stol) is not a function template, like that:
template<typename T>
T sto(std::string const & str, std::size_t *pos = 0, int base = 10);
and then:
template<>
int sto<int>(std::string const & str, std::size_t *pos, int base)
{
// do the stuff.
}
template<>
long sto<long>(std::string const & str, std::size_t *pos, int base)
{
// do the stuff.
}
/* etc. */
In my sense, that would be a better design, because for the moment, when I have to convert a string in whatever numerical value an user want, I have to manually manage each case.
Is there a reason to not have such a template function? Is there an assumed choice, or is this just done like that?
Looking at the description of these functions at cppref, I note the following:
... Interprets a signed integer value in the string str.
1) calls std::strtol(str.c_str(), &ptr, base)...
and strol a "C" standard function that's also available in C++.
Reading further, we see: (for the c++ sto* functions):
Return value
The string converted to the specified signed integer type.
Exceptions
std::invalid_argument if no conversion could be performed
std::out_of_range if the converted value would fall out of the range of the result type or if the underlying function (std::strtol or
std::strtoll) sets errno to ERANGE.
So while I have no original source for this, and indeed have never worked with these functions, I would guess that:
TL;DR : These functions are C++-ish wrappers around already existing C/C++ functions -- strtol* -- so they resemble these functions as close as possible.
I have to manage manually each case. Is there a reason to not have such a template function?
In case of such questions, Eric Lippert (C#) usually says something along the lines:
If a feature is missing, then it's missing because noone implemented it yet. And that's because either noone else earlier wanted yet, or because it was considered not worth the effort, or because it couldn't have been finished before publishing the current release".
Here, I guess it's the "not worth" part, but I have neither asked the commitee about, nor managed to find any answer in old questions and faqs. I didn't spend much time searching though.
I say this because I suppose that most common of these functions' functionality (if not all of) is already contained in stream classes, like istringstream. Just like cin/etc, this one also has an all-having operator >>, overloaded for all base numeric types (and more).
Furthermore, the stream manipulators like std::hex (std::setbase) already solve the problem of passing various type-dependent configuration parameters to the actual conversion functions. No problems with mixed function signatures (like those mentioned by DavidHaim in his answer). Here's just a single operator>>.
So.. since if we have it in streams, if we already can read numbers/etc from strings with simple foo >> bar >> setbase(42) >> baz >> ..., then I think it was not worth the effort to add more complicated layers to old C runtime functions.
No proof for that though. Just a hunch.
The problem with template specialization is that the specialization requires you to match the original template function signature, so each specialization must implement the interface of (string,pos,base).
If you would like to have some other type which does not follows this interface, you are in trouble.
Suppose that, in the future, we would like to have sto<std::pair<int,int>>. We will want to have pos and base for the first and the second stringified integer. we would like the signature to be in the form of string,pos1,base1,pos2,base2. Since sto signature is already set, we cannot do it.
You can always wrap std::sto* in your implementation of sto for integral types, but you cannot do that the other way around.
The purpose of these functions is to provide simple conversions for common cases. They are not intended as a general-purpose conversion suite. std::ostringstream is much better for that kind of thing.
In my sense, there would be a better design, because for the moment,
when I have to convert a string in whatever numerical value an user
want, I have to manage manually each case.
No, it would not. Templates goal (deliberately setting T-MP apart) is not to replace overloading; you should always prefer overloading to templates. Actually, it's something the language already does for you! Between a candidate function and a possible template instantation, the former will be prefered. Using language features for the sake of it is bad.
I don't see how templates could help either. Whatever type the user decides to input, it won't be known till runtime, and template types are deduced at compile time. C++ is a statically typed language. In this case, templates will just add an unneeded layer of complexity over normal function overloading.
The basic question:
Edit: v-The question-v
class foo {
public:
constexpr foo() { }
constexpr int operator()(const int& i) { return int(i); }
}
Performance is a non-trivial issue. How does the compiler actually compile the above? I know how I want it to be resolved, but how does the specification actually specify it will be resolved?
1) Seeing the type int has a constexpr constructor, create a int object and compile the string of bytes that make the type from memory into the code directly?
2) Replace any calls to the overload with a call to the 'int's constructor that for some unknown reason int doesn't have constexpr constructors? (Inlining the call.)
3) Create a function, call the function, and have that function call 'int's consctructor?
Why I want to know, and how I plan to use the knowledge
edit:v-Background only-v
The real library I'm working with uses template arguments to decide how a given type should be passed between functions. That is, by reference or by value because the exact size of the type is unknown. It will be a user's responsibility to work within the limits I give them, but I want these limits to be as light and user friendly as I can sanely make them.
I expect a simple single byte character to be passed around in which case it should be passed by value. I do not bar 300mega-byte behemoth that does several minuets of recalculation every time a copy constructor is invoked. In which case passing by reference makes more sense. I have only a list of requirements that a type must comply with, not set cap on what a type can or can not do.
Why I want to know the answer to my question is so I can in good faith make a function object that accepts this unknown template, and then makes a decision how, when, or even how much of a object should be copied. Via a virtual member function and a pointer allocated with new is so required. If the compiler resolves constexpr badly I need to know so I can abandon this line of thought and/or find a new one. Again, It will be a user's responsibility to work within the limits I give them, but I want these limits to be as light and user friendly as I can sanely make them.
Edit: Thank you for your answers. The only real question was the second sentence. It has now been answered. Everything else If more background is required, Allow me to restate the above:
I have a template with four argument. The goal of the template is a routing protocol. Be that TCP/IP -unlikely- or node to node within a game -possible. The first two are for data storage. They have no requirement beyond a list of operators for each. The last two define how the data is passed within the template. By default this is by reference. For performance and freedom of use, these can be changed define to pass information by value at a user's request.
Each is expect to be a single byte long. They could in the case of metric for a EIGRP or OSFP like protocol the second template argument could be the compound of a dozen or more different variable. Each taking a non-trival time to copy or recompute.
For ease of use I investigate the use a function object that accepts the third and fourth template to handle special cases and polymorphic classes that would fail to function or copy correctly. The goal to not force a user to rebuild their objects from scratch. This would require planning for virtual function to preform deep copies, or any number of other unknown oddites. The usefulness of the function object depends on how sanely a compiler can be depended on not generate a cascade of function calls.
More helpful I hope?
The C++11 standard doesn't say anything about how constexpr will be compiled down to machine instructions. The standard just says that expressions that are constexpr may be used in contexts where a compile time constant value is required. How any particular compiler chooses to translate that to executable code is an implementation issue.
Now in general, with optimizations turned on you can expect a reasonable compiler to not execute any code at runtime for many uses of constexpr but there aren't really any guarantees. I'm not really clear on what exactly you're asking about in your example so it's hard to give any specifics about your use case.
constexpr expressions are not special. For all intents and purposes, they're basically const unless the context they're used in is constexpr and all variables/functions are also constexpr. It is implementation defined how the compiler chooses to handle this. The Standard never deals with implementation details because it speaks in abstract terms.
I'm still relatively new to C++ and I can't seem to figure out the difference in the following two ways of coding a function that may take one parameter or maybe two or three or more. Anyway, here's my point
function overload:
int aClass::doSomething(int required)
{
//DO SOMETHING
}
int aClass::doSomething(int required, int optional)
{
//DO SOMETHING
}
how is this different to, default value:
int aClass::doSomething(int required, int optional = 0)
{
//DO SOMETHING
}
I know in different circumstances one may be more suitable than another but what kinds of things should I be aware of when choosing between each of these options?
There are several technical reasons to prefer overloading to default arguments, they are well laid out in Google's C++ Style Guide in the Default Arguments section:
Function pointers are confusing in the presence of default arguments,
since the function signature often doesn't match the call signature.
Adding a default argument to an existing function changes its type,
which can cause problems with code taking its address. Adding function
overloads avoids these problems.
and:
default parameters may result in bulkier code since they are
replicated at every call-site -- as opposed to overloaded functions,
where "the default" appears only in the function definition.
On the positive side it says:
Often you have a function that uses default values, but occasionally
you want to override the defaults. Default parameters allow an easy
way to do this without having to define many functions for the rare
exceptions.
So your choice will depend on how relevant the negative issues are for your application.
First off, you're talking about overloading, not overriding. Overriding is done for virtual functions in a derived class. Overloading refers to the same function name with a different signature.
The difference is logical - in the first case (2 versions), the two functions can behave completely different, whereas the second case will have more or less the same logic. It's really up to you.
The compiler doesn't care which of these you use. Imagine that you wrote it as two constructors, and they ended up about 20 lines long. Further imagine that 19 of the lines were identical, and the different line read
foo = 0;
in one version and
foo = optional;
in the other. In this situation, using an optional parameter makes your code far more readable and understandable. In another language, that didn't have optional parameters, you'd implement this by having the one-parameter version call the two parameter version and pass zero to it as the second parameter.
Now imagine a different pair of constructors or functions that again are about 20 lines long but are entirely different. For example the second parameter is an ID, and if it's provided, you look stuff up in the database and if it's not you set values to nullptr, 0, and so on. You could have a default value (-1 is popular for this) but then the body of the function would be full of
if (ID == -1)
{
foo = 0;
}
else
{
foo = DbLookup(ID);
}
which could be hard to read and would make the single function a lot longer than the two separate functions. I've seen functions with one giant if that eseentially split the whole thing into two separate blocks with no common code, and I've seen the same condition tested 4 or 5 times as a calculation progresses. Both are hard to read.
That's the thing about C++. There are lots of ways to accomplish most things. But those different ways serve different purposes, and once you "get" the subtle differences, you will write better code. In this case "better" means shorter, faster (all those ifs cost execution time), and more expressive - people reading it can understand your intentions quickly.
You are making use of the overloading feature, if you provide several constructors. The advantage in this case is, that you can react differently in every constructor on the passed arguments. If that is of importance use overloading.
If you can provide decent default values for your parameters and these wouldn't affect the proper running of your code, use default parameters.
See here for a thread on SO.
I'm experimenting with variable arguments in C++, using va_args. The idea is useful, and is indeed something I've used a lot in C# via the params functionality. One thing that frustrates me is the following excerpt regarding va_args, above:
Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list).
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself. I would like to perform something like the following:
void fcn(int arg1 ...)
{
va_list argList;
va_start(argList, arg1);
int numRemainingParams = //function that returns number of remaining parameters
for (int i=0; i<numRemainingParams; ++i)
{
//do stuff with params
}
va_end(argList);
}
To reiterate, the documentation above suggests that va_arg doesn't determine whether the retrieved arg is the last in the list. But I feel this information must be accessible in some manner.
Is there a standard way of achieving this?
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself.
Nonetheless, it is true. C/C++ do not put markers on the end of the argument list, so the called function really does not know how many arguments it is receiving. If you need to mark the end of the arguments, you must do so yourself by putting some kind of marker at the end of the list.
The called function also has no idea of the types or sizes of the arguments provided. That's why printf and friends force you to specify the precise datatype of the value to interpolate into the format string, and also why you can crash a program by calling printf with a bad format string.
Note that parameter passing is specified by the ABI for a particular platform, not by the C++/C standards. However, the ABI must allow the C++/C standards to be implementable. For example, an ABI might want to pass parameters in registers for efficiency, but it might not be possible to implement va_args easily in that case. So it's possible that arguments are also shadowed on the stack. In almost no case is the stack marked to show the end of the argument list, though, since the C++/C standards don't require this information to be made available, and it would therefore be unnecessary overhead.
The way variable arguments work in C and C++ is relatively simple: the arguments are just pushed on the stack and it is the callee's responsibility to somewhat figure out what arguments there are. There is nothing in the standard which provides a way to determine the number of arguments. As a result, the number of arguments are determined by some context information, e.g., the number of elements referenced in a format string.
Individual compilers may know how many elements there are but there is no standard interface to obtain this value.
What you could do instead, however, is to use variadic templates: you can determine very detailed information on the arguments being passed to the function. The interface looks different and it may be necessary to channel the arguments into some sort of data structure but on the upside it would also work with types you cannot pass using variable arguments.
No, there isn't. That's why variable arguments are not safe. They're a part of C, which lacks the expressiveness to achieve type safety for "convenient" variadic functions. You have to live with the fact that C contains constructions whose very correctness depends on values and not just on types. That's why it is an "unsafe language".
Don't use variable arguments in C++. It is a much stronger language that allows you to write equally convenient code that is safe.
No, there's no such way. If you have such a need, it's probably best to pack those function parameters in a std::vector or a similar collection which can be iterated.
The variable argument list is a very old concept inherited from the C history of C++. It dates back to the time where C programmers usually had the generated assembler code in mind.
At that time the compiler did not check at all if the data you passed to a function when calling it matched the data types the function expected to receive. It was the programmer's responsibility to do that right. If, for example, the caller called the function with a char and the function expected an int the program crashed, although the compiler didn't complain.
Today's type checking prevents these errors, but with a variable argument list you go back to those old concepts including all risks. So, don't use it if you can avoid it somehow.
The fact that this concept is several decades old is probably the reason that it feels wrong compared to modern concepts of safe code.