I'm currently working on a code using mostly boost but moving more and more to C++11 and it's std library.
There I had crash while passing an empty boost::function as a callback to a std::function:
#include <boost/function.hpp>
#include <functional>
#include <iostream>
int main()
{
boost::function <void(void)> boost_f;
std::function <void(void)> std_f;
std::cout << "used " << (std_f!=nullptr) << " " << (!boost_f.empty()) << "\n";
boost_f = boost::function<void(void)>();
std_f = boost_f;
std::cout << "used " << (std_f!=nullptr) << " " << (!boost_f.empty()) << "\n";
if( std_f )
std_f();
}
The std::function claims it has a valid target, but the empty boost::function throws an exception:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_function_call> >'
what(): call to empty boost::function
Tested with gcc-6.3.1 and clang-4.0.
How could I avoid this problem? Could this be fixed so that an empty boost::function assigned to a std::function gives an empty std::function? Or could I check the std::function explicitly for an empty boost::function assigned to it?
Only avoiding the exception is not the intended solution because the function should behave differently dependent on the callback set or not (and it is often not set, so catching the exception should be avoided too).
How about this:
if(std_f)
{
if( std_f.target_type()==typeid(boost::function<void(void)>))
{
auto boostF=std_f.target<boost::function<void(void)>>();
if(boostF&&*boostF)
std_f();
else
{
std::cout<<"empty boost function"<<std::endl;
}
}
else
std_f();
}
Related
according to cplusplus.com on std::bad_alloc
Type of the exceptions thrown by the standard definitions of operator new and operator new[] when they fail to allocate the requested storage space.
However, in my code the new operator is not used:
#include <iostream>
#include <boost/filesystem.hpp>
#include <cstdint>
using namespace std;
using namespace boost::filesystem;
int main()
{
path p{};
std::cin >> p;
if (exists(p)) // does p actually exist?
{
if (is_regular_file(p)) // is p a regular file?
cout << p << " size is " << file_size(p) << '\n';
else if (is_directory(p)) // is p a directory?
cout << p << "is a directory\n";
else
cout << p << "exists, but is neither a regular file nor a directory\n";
}
else
cout << p << "does not exist\n";
return 0;
}
(code taken from boost filesystem tutorial)
and yet the console says:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
I've got the following test.cpp file
#include <string>
#include <functional>
#include <unordered_map>
#include <iostream>
class Mystuff {
public:
std::string key1;
int key2;
public:
Mystuff(std::string _key1, int _key2)
: key1(_key1)
, key2(_key2)
{}
};
namespace std {
template<>
struct hash<Mystuff *> {
size_t operator()(Mystuff * const& any) const {
size_t hashres = std::hash<std::string>()(any->key1);
hashres ^= std::hash<int>()(any->key2);
std::cout << "Hash for find/insert is [" << hashres << "]" << std::endl;
return (hashres);
}
};
}; /* eof namespace std */
typedef std::unordered_map<Mystuff *, Mystuff *>mystuff_map_t;
mystuff_map_t map;
int insert_if_not_there(Mystuff * stuff) {
std::cout << "Trying insert for " << stuff->key1 << std::endl;
if (map.find(stuff) != map.end()) {
std::cout << "It's there already..." << std::endl;
return (-1);
} else {
map[stuff] = stuff;
std::cout << "Worked..." << std::endl;
}
return (0);
}
int main(){
Mystuff first("first", 1);
Mystuff second("second", 2);
Mystuff third("third", 3);
Mystuff third_duplicate("third", 3);
insert_if_not_there(&first);
insert_if_not_there(&second);
insert_if_not_there(&third);
insert_if_not_there(&third_duplicate);
}
You can compile with g++ -o test test.cpp -std=gnu++11.
I don't get what I'm doing wrong with it: the hash keying algorithm is definitely working, but for some reason (which is obviously in the - bad - way I'm doing something), third_duplicate is inserted as well in the map, while I'd wish it wasn't.
What am I doing wrong?
IIRC unordered containers need operator== as well as std::hash. Without it, I'd expect a compilation error. Except that your key is actually MyStuff* - the pointer, not the value.
That means you get the duplicate key stored as a separate item because it's actually not, to unordered_map, a real duplicate - it has a different address, and address equality is how unordered_map is judging equality.
Simple solution - use std::unordered_map<Mystuff,Mystuff> instead. You will need to overload operator== (or there's IIRC some alternative template, similar to std::hash, that you can specialize). You'll also need to change your std::hash to also accept the value rather than the pointer.
Don't over-use pointers in C++, especially not raw pointers. For pass-by-reference, prefer references to pointers (that's a C++-specific meaning of "reference" vs. "pointer"). For containers, the normal default is to use the type directly for content, though there are cases where you might want a pointer (or a smart pointer) instead.
I haven't thoroughly checked your code - there may be more issues than I caught.
Can somebody explain the behavior of the following code?
When I explicitely convert my lambda to an std::function, the lambda correctly captures my variable n.
When it is implicitly converted to an std::function (using a temporary), then the capture fails.
I am using g++-4.9 (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
std::shared_ptr<std::thread> call(const std::function<void()>& functor)
{
// Execute our functor asynchronously
return std::make_shared<std::thread>([&functor]
{
// Make sure all temporary are deallocated
std::this_thread::sleep_for(std::chrono::seconds(1));
// Execute our functor
functor();
});
}
int main()
{
int n{};
std::cout << "in main " << &n << std::endl;
// -> in main 0x7fffd4e1a96c
auto lambda = [&n]
{
std::cout << "in lambda " << &n << std::endl;
};
// Here we do an explicit convertion to std::function
std::cout << "explicit convertion" << std::endl;
auto function = std::function<void()>{ lambda };
auto pThreadFunction = call(function);
pThreadFunction->join();
// -> in lambda 0x7fffd4e1a96c
// Here we use an implicit convertion to std::function
std::cout << "implicit convertion" << std::endl;
auto pThreadLambda = call(lambda);
pThreadLambda->join();
// -> in lambda 0
return 0;
}
The lifetime of a temporary constructed for binding to a const reference function parameter is the full-expression containing that function call, so your thread function is referring to a dangling reference.
You should only capture variables into a thread function by reference if you can guarantee that the lifetime of the variable contains the lifetime of the thread, as you have done in the case where function is a local variable in main.
One alternative would be to call join within the full-expression that constructs the temporary:
call(lambda)->join();
Another more general solution would be to capture functor by value in your thread function.
My question is : is it legal to return a reference to an input variable which is passed by reference.
I borrow the example from C++: Life span of temporary arguments? and return by rvalue reference
#include <iostream>
#include <string>
class MatrixClass
{
public:
int m_value;
std::string m_str;
MatrixClass(int a)
{
m_value = a;
std::cout << "hello: " << m_value << '\n';
}
MatrixClass(const MatrixClass& A)
{
m_value = A.m_value;
std::cout << "hello: " << m_value << '\n';
if (A.m_str == "temp_in_*")
{
std::cout << "string: " << "copied from temp_in_*" << '\n';
}
}
void operator=(const MatrixClass& A)
{
m_value = A.m_value;
std::cout << "hello: " << m_value << '\n';
if (A.m_str == "temp_in_*")
{
std::cout << "string: " << "copied from temp_in_*" << '\n';
}
}
~MatrixClass()
{
std::cout << "bye: " << m_value << '\n';
if (m_str == "temp_in_*")
{
std::cout << "string: " << "temp_in_*" << '\n';
}
}
};
MatrixClass& operator+(MatrixClass& tempClassA, MatrixClass& tempClassB)
{
tempClassA.m_value += tempClassB.m_value;
return tempClassA;
}
MatrixClass operator*(MatrixClass& tempClassA, MatrixClass& tempClassB)
{
MatrixClass Temp(101010);
Temp.m_value = tempClassA.m_value * tempClassB.m_value;
Temp.m_str = "temp_in_*";
return Temp;
}
int main()
{
MatrixClass A1(2);
MatrixClass A2(3);
MatrixClass A3(10);
MatrixClass A4(11);
MatrixClass A5(12);
std::cout << "start of expression " << '\n';
MatrixClass A6(0);
A6 = A1 * A2 + A3 * A4 + A5 * A6;
std::cout << "end of expression " << '\n';
std::cout << "A6.m_value: " << A6.m_value << '\n';
std::system("pause");
}
the operator return a reference to its input which is a temporary variable, and pass
it to another operator: operator*(A1, A2) return a temporary variable, also operator*(A3, A4), operator*(A5, A6)
Is there any problem with the lifetime of the temporary variables ? I am developing a Matrix class.
What happens if the expression is more complicated, such as:
(A+B*C)*((A*B + C)*A)
A general question is (take from return by rvalue reference)
is this possible:
change
A compute(A&& v)
{
(do something to v)
return v;
}
to
A& compute(A& v)
{
(do something to v)
return v;
}
Yes, it is legal for a function to return references to input parameters, in the sense that it will compile and there are many uses where it will work without problems. The lifetime of any temporaries created in an expression is the lifetime of the full expression or statement, so as long as the reference is not used beyond the expression, the usage should work fine. It is somewhat risky, though, because the caller may not be aware of the reference propagation the function does, and the special rules for extension of temporary lifetimes don't generally apply when the reference is passed through an intermediary function.
Your examples involve modifying and returning a reference to non-const lvalue instance. These types of uses, in general, will be harder to run into the pitfalls than references to const or references to rvalues. A reference to non-const lvalue can't be bound to a temporary (at least not without going through some hoops to trick the compiler), so you will generally have to pass an actual l-value (non-temporary) named variable (or other long-lived object) into them. When that reference is then passed out of the function as a return value, it will refer to whatever long-lived object was passed in. (You can still get into trouble if you don't properly manage lifetimes, of course, but at least the lifetimes we're talking about in this case are generally more than a single statement/expression.)
If you pass rvalue references through your function, and especially if they get translated to a non-const lvalue somewhere down the expression tree (which is somewhat easy to do since the language, as a safety feature, decays rvalues into lvalues whenever they're bound to a name), the temporary nature of the reference can be lost and it is easier to accidentally bind the reference to a long-lived reference, which would outlive the temporary that it is bound to (which generally won't live beyond the statement/full-expression in which it is created). This is why I generally favor returning (and usually passing) r-values by value rather than by reference. Then, the compiler is more aware of the lifetime issues and the usages are generally more foolproof. In many cases, the compiler can elide the move constructions anyway, and when it can't, moves are generally cheap.
Given a class A with two constructors, taking initializer_list<int> and initializer_list<initializer_list<int>> respectively, then
A v{5,6};
calls the former, and
A v{{5,6}};
calls the latter, as expected. (clang3.3, apparently gcc behaves differently, see the answers. What does the standard require?)
But if I remove the second constructor, then A v{{5,6}}; still compiles and it uses the first constructor. I didn't expect this.
I thought that A v{5,6} would be the only way to access the initializer_list<int> constructor.
(I discovered this while playing around with std::vector and this question I asked on Reddit, but I created my own class A to be sure that it wasn't just a quirk of the interface for std::vector.)
I think this answer might be relevant.
Yes, this behaviour is intended, according to §13.3.1.7 Initialization
by list-initialization
When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:
— Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of
the initializer list as a single argument.
— If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all
the constructors of the class T and the argument list consists of the
elements of the initializer list.
In gcc I tried your example. I get this error:
error: call of overloaded 'A(<brace-enclosed initializer list>)' is ambiguous
gcc stops complaining if I use three sets of brace. i.e.:
#include <iostream>
#include <vector>
#include <initializer_list>
struct A {
A (std::initializer_list<int> il) {
std::cout << "First." << std::endl;
}
A (std::initializer_list<std::initializer_list<int>> il) {
std::cout << "Second." << std::endl;
}
};
int main()
{
A a{0}; // first
A a{{0}}; // compile error
A a2{{{0}}}; // second
A a3{{{{0}}}}; // second
}
In an attempt to mirror the vector's constructors, here are my results:
#include <iostream>
#include <vector>
#include <initializer_list>
struct A {
A (std::initializer_list<int> il) {
std::cout << "First." << std::endl;
}
explicit A (std::size_t n) {
std::cout << "Second." << std::endl;
}
A (std::size_t n, const int& val) {
std::cout << "Third." << std::endl;
}
A (const A& x) {
std::cout << "Fourth." << std::endl;
}
};
int main()
{
A a{0};
A a2{{0}};
A a3{1,2,3,4};
A a4{{1,2,3,4}};
A a5({1,2,3,4});
A a6(0);
A a7(0, 1);
A a8{0, 1};
}
main.cpp:23:10: warning: braces around scalar initializer
A a2{{0}};
^~~
1 warning generated.
First.
First.
First.
First.
First.
Second.
Third.
First.