The following code:
#include <iostream>
using namespace std;
struct A{int number=10;};
int main()
{
A* a = new A();
cout<<"A val: "<< a==nullptr?"":a->number<<endl;
}
compiling on gcc 4.7 with c++11 gives:
error: invalid operands of types 'int' and '' to binary 'operator <<'
I do not understand why, what would be to proper way to do it? I want to keep null checks as short as possible as I expect them to be very common.
First: yes, you can use the ternary operator for an std::ostream, but beware of operator precedence. If you are going to do so, you need to do something like this:
cout << "My name is: " << (my != nullptr ? my->name() : "don't know") << '\n';
In other words, encapsulate the ternary expression in parentheses.
Second, the second and third operands must be convertible to the same type. In other words, your example won't work because you are trying to insert a string literal ("") if a is null, or the actual number (a->number, which is of type int) if a is not null.
Third, you need to fix the syntax. But #quamrana already addressed that one.
You are finding that operator << binds differently than you expect.
Use:
cout << "A val: " << (a==nullptr ? "" : a->number) << endl;
(or have you just made a typo and missed the : from ?:)
Related
Consider this snippet:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
char c[] = {'a','b','c','\0'};
char *pc = c;
char **ppc = &pc;
cout << ppc[0] << endl;
}
This prints abc as output. Why does the index of a pointer to pointer to char return the whole string? Here, ppc only points to another pointer that points to a single char. How does it know about the whole string and why would it return it?
You have to understand what std::cout is and why it treats a char* as a "string".
Lets start:
std::cout is an instance of an std::ostream and std::ostream has a lot of operators. What does it mean?
The implementation of std::ostream can, but only as an example here, written like:
class ostream
{
// ... a lot more code for constructors and others
ostream& operator <<( const int );
ostream& operator <<( const double );
ostream& operator <<( char* ); <<< this is the implementation you search for!
// a long list of more special overloads follow
};
And the implementation simply puts out the "string" which the char* points to.
What you see is simply a special overload of the operator<< for the std::ostream class.
OK, the real implementation uses a non-member overload, but that is not important for understanding how std::ostream works in principal.
For more details see: std::ostream::operator<<()
Character and character string arguments (e.g., of type char or const char*) are handled by the non-member overloads of operator<<. Attempting to output a character using the member function call syntax (e.g., std::cout.operator<<('c');) will call one of overloads (2-4) and output the numerical value. Attempting to output a character string using the member function call syntax will call overload (7) and print the pointer value instead.
These are equivalent:
cout << ppc[0] << endl;
cout << *( ppc + 0 ) << endl;
cout << *ppc << endl;
cout << *(&pc) << endl;
cout << pc << endl;
Sample program:
#include <iostream>
#include <string>
#include <vector>
template <typename T>
void print(const T& _vec)
{
for( auto c: _vec )
std::cout << c << ",";
}
typedef std::vector<std::string> vecstr_t;
struct Trade
{
explicit Trade(vecstr_t&& vec) : _vec(vec )
{
}
vecstr_t _vec;
};
int main()
{
vecstr_t tmpV = {"ONE", "TWO", "THREE", "FOUR"};
std::cout << "size 1:" << tmpV.size() << "\t"; print(tmpV); std::cout << "\n" ;
Trade t(std::move(tmpV));
std::cout << "size 2:" << tmpV.size() << "\t"; print(tmpV); std::cout << "\n" ; // expted tmpV should be e,pty but it has original contents
print(t._vec);
}
I expect size 2: should be ZERO but output is:
size 1:4 ONE,TWO,THREE,FOUR,
size 2:4 ONE,TWO,THREE,FOUR,
ONE,TWO,THREE,FOUR,
explicit Trade(vecstr_t&& vec) : _vec(vec)
{}
In the constructor above, even though vec is of type rvalue reference to vecstr_t, it is itself an lvalue. The basic rule to remember is - if it has a name, it's an lvalue.
There are very few contexts where an lvalue may automatically be moved from (such as the return statement of a function that returns an object by value), but a constructor's mem-initializer list is not one of them.
In your example, _vec is copy constructed from vec. If you want it to be move constructed instead, use std::move.
explicit Trade(vecstr_t&& vec) : _vec(std::move(vec))
{}
Now the second call to print will not print anything. Note that technically the second call could print a non-zero size because the contents of a moved from vector are unspecified. But on most (probably all) implementations, you'll see an empty vector.
Live demo
Your comment below says your intent is to accept both rvalues and lvalues, move only in the case of the former, and copy the argument otherwise. As currently written, your constructor will only accept rvalues, and not lvalues. There are a few different options to achieve what you want.
The easiest probably is to change the parameter so that it's taking the argument by value, and then unconditionally move.
explicit Trade(vecstr_t vec) : _vec(std::move(vec))
{}
The drawback with this approach is that you may incur an additional move construction of the vector, but move constructing a vector is cheap, and you should go with this option in most cases.
The second option is to create two overloads of the constructor
explicit Trade(vecstr_t&& vec) : _vec(std::move(vec)) {}
explicit Trade(vecstr_t const& vec) : _vec(vec) {}
The drawback with this one is that the number of overloads will increase exponentially as the number of constructor arguments increases.
The third option is to use perfect forwarding.
template<typename V>
explicit Trade(V&& vec) : _vec(std::forward<V>(vec)) {}
The code above will preserve the value category of the argument passed to the constructor when it forwards it to construct _vec. This means that if vec is an rvalue, the vecstr_t move constructor will be called. And if it is an lvalue, it will be copied from.
The drawback with this solution is that your constructor will accept any type of argument, not just a vecstr_t, and then the move/copy construction in the mem-initializer list will fail if the argument is not convertible to vecstr_t. This may result in error messages that are confusing to the user.
I know this is an easy question but I can't seem to find a specific answer anywhere!
Going through test code for threads in c++11, and don't understand the meaning of this template function statment:
packaged_task<int(int)> task1(&myComputation);
Not sure what 'int(int)' means in this code. I understand in general that what is passed into the brackets < > is the type of what is being passed to the template definition. Is this some sort of type casting?
Thanks!
In this context, the int(int) represents the type signature of a function pointer to a function that takes one parameter (an int), and returns an int. So, if I were to write:
int myFunction(int value) {
std::cout << value << std::endl;
}
std::packaged_task<int(int)> myPackagedTask{&myFunction};
the packaged_task would now contain a function pointer to myFunction. Following, this would be an error:
int mySecondFunction(int value, int secondValue) {
std::cout << value << " : " << secondValue << std::endl;
}
std::packaged_task<int(int)> myPackagedTask{&mySecondFunction}; //compile error, mySecondFunction does not match signature int(int)
Short version:
I need to pass a template class a parameter pack, which is the result of applying a function to another parameter pack. This needs to work within a using statement.
Background:
As a challenge, I'm writing a generic C++11 version of python's zip(). In order to do so, I have written a generic zipIterator template class which can be used to iterate over many iterators simultaneously, yielding a tuples of their values. For example:
#include "zip.hpp"
#include <iostream>
#include <vector>
#include <tuple>
int main(){
std::vector<int> vec = {0,1,2,3};
char arr[] = {'a','b', 'c'};
zipIterator<decltype(vec.begin()), char*, decltype(vec.rbegin())>
itr(vec.begin(), std::begin(arr), vec.rbegin());
zipIterator<decltype(vec.begin()), char*, decltype(vec.rbegin())>
end(vec.end(), std::end(arr), vec.rend());
for(; itr!=end; ++itr){
std::cout << "(" << std::get<0>(*itr) << ", " << std::get<1>(*itr)
<< ", " << std::get<2>(*itr) << ")" << std::endl;
}
}
//output:
//(0, a, 3)
//(1, b, 2)
//(2, c, 1)
The Problem
I would like to make a zip container class which can be passed containers, and which zips over them by calling std::begin() and std::end() on each one. So far I have this:
template<typename... Containers>
class zip{
public:
using iterator = zipIterator<???>;
zip(Containers... cs) : begin_(iterator(std::begin(cs)...)),
end_(iterator(std::end(cs)...)){};
iterator begin() {return begin_;}
iterator end() {return end_;}
private:
iterator begin_;
iterator end_;
};
My question is: what goes in the place of ??? to make this work? So far I have tried
std::begin(std::declval<Containers>())...,
decltype(std::begin(Containers)...),
std::result_of<std::begin(Containers)>::type...,
and many more variations on this.
Sorry if this is a repeat. I read the following Stack Overflow answers and they all seem to be related, but I don't think they are quite what I am looking for:
C++11 call member function on template parameter pack of base classes if present
How to make generic computations over heterogeneous argument packs of a variadic template function?
Calling a function for each variadic template argument and an array
using iterator = zipIterator<decltype(std::begin(std::declval<Containers&>()))...>;
The basic idea is that ... expands the pattern on its left. Here, the pattern is decltype(std::begin(std::declval<Containers&>())) - the type of the return value of std::begin when called on an lvalue of type Containers.
I recently came across the following code that uses syntax I have never seen before:
std::cout << char('A'+i);
The behavior of the code is obvious enough: it is simply printing a character to stdout whose value is given by the position of 'A' in the ASCII table plus the value of the counter i, which is of type unsigned int.
For example, if i = 5, the line above would print the character 'F'.
I have never seen char used as a function before. My questions are:
Is this functionality specific to C++ or did it already exist in strict C?
Is there a technical name for using the char() keyword as a function?
That is C++ cast syntax. The following are equivalent:
std::cout << (char)('A' + i); // C-style cast: (T)e
std::cout << char('A' + i); // C++ function-style cast: T(e); also, static_cast<T>(e)
Stroustroup's The C++ programming language (3rd edition, p. 131) calls the first type C-style cast, and the second type function-style cast. In C++, it is equivalent to the static_cast<T>(e) notation. Function-style casts were not available in C.
This is not a function call, it's instead a typecast. More usually it's written as
std::cout << (char)('A'+i);
That makes it clear it's not a function call, but your version does the same. Note that your version might only be valid in C++, while the one above work in both C and C++. In C++ you can also be more explicit and write
std::cout << static_cast<char>('A'+i);
instead.
Not that the cast is necessary because 'A'+i will have type int and be printed as an integer. If you want it to be interpreted as a character code you need the char cast.