Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
So, before quite some exposition, here comes my question:
Why is there no support for multiple return variables/values in C++ (yet)?
To give you some more notes:
What (if any) is conceptually a problem with multiple return values and c++?
Is there something in the way the compiler implements returing a values from a function which makes multiple return values impossible/inefficient?
Having worked a lot with lua recently I've come to ask myself why C++ does not permit to return multiple values/variables from a function. To illustrate, let me give you a lua example:
-- get the first four values of the fibonacci sequence
local function fib4()
return 1, 1, 2, 3
local fib0, fib1, fib2, fib3 = fib4()
Being able to return multiple variables/values at once is a very useful feature indeed, which I typically emulate in the C++ world by creating structs (essentially collecting the variables in a wrapper) which are returned by the function in question. If one uses this approach a lot, the soure files will be cluttered with structs each containing some variables; none of these struct needs to be an actual object (and is implemented as a complete object). In a way the conceptual problem is somewhat similar the one resulting from using structs for creating functors [instead of lambdas]:
It destroys locality
It introduces objects which are not conceptually objects but rather a helper
On the pro side it increases code readability:
struct point_three_dim_t {
double x;
double y;
double z;
};
point_three_dim_t point = getCollisionPoint();
However, a priori you don't know whether the members representing the coordinates are named x, y and z or first, second and third. So again, you have to check how point_three_dim_t was defined. This would not be the case if
double x, y, z = getCollisionPoint();
were correct syntax.
Using C++11 we can achieve conceptually the same by using either std::tuple or std::tie
std::tuple<double,double,double> getCollisionPoint();
// Using std::tie
double x, y, z;
std::tie( x, y, z ) = getCollisionPoint();
// Using std::tuple
std::tuple<double,double,double> point = getCollisionPoint();
This gets us much closer to clean and local code, however, I think neither syntax is quite as appealing as the one I'm used from scripting languages like lua.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am trying to read the documentation of the DOLFIN c++ library for finite element modelling located on this link:
https://fenicsproject.org/olddocs/dolfin/1.3.0/python/programmers-reference/index.html
but the documentation is hard to read, so for someone without c++ knowledge how you will read the following specification of parameters for the c++ method eval_cell() of the Expression class (https://fenicsproject.org/docs/dolfin/2017.2.0/python/programmers-reference/cpp/function/Expression.html):
Parameters:
double > & values (Array<) – (Array<double>) The values at the point.
Array< double > & x (const) – (Array<double>) The coordinates of the point.
ufc::cell & cell (const) – (ufc::cell) The cell which contains the given point.
After taking a look at the page t.niese linked in the comments I think this is a automatically generated documentation, with a really bad generator (like really really bad).
So, if we fix the butchered first line, realign some braces here and there and fix the position of const it might become clearer:
Parameters
const Array<double>& values1 – The values at the point.
const Array<double> &x – The coordinates of the point.
const ufc::cell &cell – The cell which contains the given point.
Meaning
You are dealing with a function that takes three parameters, the first and second are of type Array<double>, which seems to be generic container. The third parameter is of type ufc::cell, whatever this is. All three parameters are passed by reference (see the & before each variable name) and not by value. But they are not just passed as reference but actually as const reference (see the const), meaning that the function can't modify the objects you give to it.
I can't however say much about the comments for each parameter.
1 I assume the first parameter is also const, because it got the brackets, where the const is noted in the other two parameters, but this is just guessing.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am facing a problem of extracting arithmetic operation information from C++ source code. For example, I want to parse a C++ code such that I can find out the the line numbers for all the codes that conduct arithmetic operations as well as the name of the variables or literals involved in the operation and the corresponding operation type. I am interested in built-in types such as int and double as well as user-defined classes where arithmetic operators such as operator+, operator* are overloaded.
Any idea how this can be achieved?
Edit: I was hoping that some compilers might generate some intermediate results that I can utilize to achieve this goal. I did some search and it seems that libclang can generate some useful intermediate results, but I just want to get some suggestions before I spend too much time on digging into it.
You might be able use clang-query to do it. Getting the queries just right is a bit tricky, but the llvm ast matcher docs are quite useful providing examples for every matcher. It also prints line/col numbers for the matched results.
Example code:
struct complex { float r, i; };
int operator*(int a, complex b)
{
return 0;
}
int main()
{
int a = 0;
complex b;
return (a * a) + (a * b);
}
Example query that returns math expressions which have been overloaded:
match cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("-"),
hasOverloadedOperatorName("+"), hasOverloadedOperatorName("*"),
hasOverloadedOperatorName("/")))
Output:
return (a * a) + (a * b);
^~~~~
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Recently I have started looking into C++ from the basics and got to know (to my surprise) that I can give series of expressions in a single line separated by commas in some cases as below
//it'll execute all the expressions mentioned after condition seperated by comma
for(int i=0;condition;++i,++x,cout<<"in for loop"<<endl,z = z*2);
(x>y)? ++z,z1 = z*2, cout<<"printing statement"<<endl:cout<<"condition failed"<<endl,z = z/2;
Here, I have a confusion after this is working. Is it safe to code in that way or is there any problem coding in such a way?
Please clarify!!!
Correct me if i'm wrong anywhere, I'm just curious to know why most of the programmers don't use this way (I haven't seen such kind of lines anywhere)
The comma operator , evaluates each of its operands in sequence. In standardese, there is a sequence point between the evaluation of the left operand and the right operand.
In a expression which contains a comma operator, the value of the left operand is discarded and the expression takes on the value of the right operand. In both of the examples above, the comma operator is used in a void context, so none of the values are used.
So a statement like this where the value of the comma operator is not used:
exp1, exp2, exp3, exp4;
Is equivalent to the following sequence of statements:
exp1; exp2; exp3; exp4;
The first example is equivalent to the following:
for(int i=0;condition;) {
++i;
++x;
cout<<"in for loop"<<endl;
z = z*2;
}
And the second example:
if (x>y) {
++z;
z1 = z*2;
cout<<"printing statement"<<endl;
} else {
cout<<"condition failed"<<endl;
z = z/2;
}
Note that this is considerably more readable that the one-line versions. It's also easier to debug. Since debuggers typically step through code a line at a time, it breaks up the flow and is more granular.
Not indenting and spacing your code is not less costly regarding performance. It is unreadable, confusing and a pain to understand for you and for anyone who'd have to work with it.
Lot of people will prefer a well-syntaxed, beautifully and efficiently-indented code than a top-performance one. You can modify, debug and refract a code which might not work but has the advantage to be understandable.
On the other hand, very few codes remain unchanged and stay unread. There will always be a time when someone, may be you, will have to read it again and if it looks like the one if your OP, it will be very time costly to do.
It is allowed. In my opinion and i say without a reference that in general other programmers do not find your 'for' loop very readable. Sometimes in a for loop you want to do other things then just for (int i = 0; i < 10; ++i){"do something"}For example increment 'i' in every loop with two. Reading code should be like reading a text. If you are reading a book you do not want it to be unnecessary difficult.
Your other question was about the safety of the statement. The biggest problem with the code is that you might get confused about what you are doing exactly. Bugs are caused by human errors (computers are deterministic and are executing machine code which ultimately has been written by a human) and the question about safety mainly depends on how you define it.
To give you some tips. When i just started programming C++ i looked a lot on CPP reference. I will give you a link where you can read about the syntax and what is allowed/possible. On this website there are quite a lot of examples on all kinds of statements. They will in general not put 5 or 6 operations within in a single line. If there are more variables that you want to change then you might want to do that in the scope of the for loop so it will be more readable instead of inside the for loop.
http://en.cppreference.com/w/cpp/language/for
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I've been criticized (without real arguments) for using assign and compare like this in my c code:
if (!(buffer = malloc(1024))) {
// handle failure
}
instead of:
buffer = malloc(1024);
if (!buffer) {
// handle failure
}
To be clear: This is not about malloc() but only about doing assignments within condition statements.
Personally I prefer the prior version from an aesthetic point of view.
Also if I do a git grep -E "if \(\!\(.* = .*\)\)\) \{" in order to identify similar constructs in the current Linux kernel source I find a few hundred identical assignments inside if conditions, e.g. in net/ipv4/ipconfig.c:
if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
rtnl_unlock();
return -ENOMEM;
}
Also used frequently in boost:
// boost/lexical_cast/detail/converter_lexical.hpp
if (!(i_interpreter.operator <<(arg)))
return false;
// boost/iostreams/filter/newline.hpp:
if ((flags_ & f_has_LF) != 0) {
if ((success = boost::iostreams::put(dest, LF)))
flags_ &= ~f_has_LF;
} else if (boost::iostreams::put(dest, CR)) {
if (!(success = boost::iostreams::put(dest, LF)))
flags_ |= f_has_LF;
}
So - apart from your personal opinion - are there good technical arguments for or against doing an assignment and comparison in one statement?
As far as I can tell, the argument against your version tends to be along the lines of "people don't expect to see operations in a conditional". Indeed, when looking over C-like code it takes me a little extra mental effort to spot the socket, bind and listen calls when they're stuffed in an if, because I'm expecting an if's condition to check things, not do things.
But that's about it.
I honestly don't see a marked difference in readability. I prefer yours, actually.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I want to know how I can identify if my tuple is empty?
Note that I use std::tuble in conjunction with std::map as below:
typedef std::tuple<SDESType,INT32,std::string> SDesItem;
typedef std::map<SDESType,SDesItem> SDesItemMap;
Now I want to check if the second value of SDesItemMap, that is a tuple, is empty or not?
if(SDesItems[SDESType] != NULL) // this is error
std::tuple acts like three values tied together. It has no predefined "empty" or "zero" state, other than empty states of each of its members. Empty value is always contextual, and in general means a value lying outside the domain of the regular type's values.
For example, a natural number can only be 0 (or 1, depending on your definition) upward. Thus, using an int gives you a convenient way to represent a value that's outside of the domain, and should be treated irregularly.
To represent that cleanly in your example, use optional<tuple<...>> as a map value (if you want to specifically state "there's an empty value at a given key"). This type states that the possible values of the type you get by instantiating the optional template are now all of the values of the original type, and a special, nothing (/empty/none) value.
You can also state that parts of the tuple can be empty (nothing), like
tuple <
std::string, // empty string ("") can be treated as "empty state"
optional<int>, // if you don't want to treat 0 (or -1) as "empty"
>
optional<> is not a part of std:: yet, so you have to write your own implementation or use the Boost one. Another way would be using value_ptr (Boost again), but here it wouldn't probably give you any benefits.