Passing 0 to the shared pointer with deleter as the first argument - c++

I'm readin Scott Meyrse C++ and now I'm at the section about deigning interfaces. The following code is supposed to be invalid:
std::tr1::shared_ptr<Investment> // attempt to create a null
pInv(0, getRidOfInvestment); // shared_ptr with a custom deleter;
// this won’t compile
He gave the following explanation:
The tr1::shared_ptr constructor insists on its first parameter being a
pointer, and 0 isn’t a pointer, it’s an int. Yes, it’s convertible to
a pointer, but that’s not good enough in this case; tr1::shared_ptr
insists on an actual pointer.
I tried similar example myself http://coliru.stacked-crooked.com/a/4199bdf68a1d6e19
#include <iostream>
#include <memory>
struct B{
explicit B(void *){ }
};
void del(int*){ }
int main()
{
B b(0);
std::shared_ptr<int*> ptr(0, del);
}
and it compiles and runs fine even in spite of passing 0 as the first argument.
What did he mean actually? Isn't that relevant already?

One is from #include <tr1/memory>; the other is from #include <memory>. There is a difference:
http://coliru.stacked-crooked.com/a/f76ea0ef17227d9d
#include <iostream>
#include <tr1/memory>
#include <memory>
struct B{
explicit B(void *){ }
};
void del(int*){ }
int main()
{
B b(0);
std::tr1::shared_ptr<int*> ptr(0, del);
std::shared_ptr<int*> ptr2(0, del);
}
It gives the error for the tr1 version but not the current standard version.

Related

Pass reference of a smart ptr to a constructor

i use qcc (qnx 660) compiler (gcc 4.7.3).
I wanted to use a reference to an object in another object.
For this I wanted to pass this in a constructor call and copy/assign it to a member instance.
As I got undefined reference errors again and again I got annoyed and converted the whole thing in a simpler way and changed a refrenz to an int variable, see example.
I came across this question, and wanted to solve it in the answer as given by #sellibitze.
Here is my code example:
foo.hpp:
#include <memory>
#include <utility>
class foo { public:
explicit foo(std::shared_ptr<int> stuff);
private:
std::shared_ptr<int> mstuff;
};
foo.cpp:
#include "foo.hpp"
explicit foo::foo(std::shared_ptr<int> stuff)
:mstuff(std::move(stuff))
{
std::cout << "done" << std::endl;
}
main.cpp:
#include <cstdlib>
#include <iostream>
#include "foo.hpp"
int main(int argc, char *argv[])
{
foo my_foo(std::make_shared<int>(10));
}
error message of compiler:
main.cpp:11: undefined reference to `foo::foo(std::shared_ptr)'
As this didn't work either, I got suspicious and recreated the example in the online compiler, https://godbolt.org/z/83hTMq1ef.
With the gcc 4.7.3 various messages come.
With a gcc >9 you only get this message :
:17:1: error: 'explicit' outside class declaration 17 |
explicit foo::foo(std::shared_ptr cnt)
| ^~~~~~~~ Compiler returned: 1
What is the smartest way to pass a shared_ptr with gcc version 4.7.3?

boost::multi_index_container crashes with _com_ptr_t objects

I try to use boost::multi_index_container with _com_ptr_t objects.
Code compiles with no warnings but crashes in runtime.
Standard containers (std::set, map etc) work perfectly with such objects.
Is it possible to use multi_index_container with _com_ptr_t?
Sample code here:
#include "stdafx.h"
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
using CTest =
boost::multi_index_container<MSXML2::IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc)); <-- crash here
::CoUninitialize();
return 0;
}
I notice that the multi_index_container you've defined holds pointers of type MSXML2::IXMLDOMDocument2Ptr, yet doc is of type MSXML2::IXMLDOMDocumentPtr (without the 2). I'm assuming this is OK, as the problem is really not related to this discrepancy.
Boost.MultiIndex does support move semantics, so you can use std::move as you please.
The actual problem is that _com_ptr_t has a weird, destructive operator& overload returning a pointer to the wrapped interface. This confuses the internal code of Boost.MultiIndex. You can easily bypass this overload as follows:
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
struct IXMLDOMDocument2Ptr:MSXML2::IXMLDOMDocument2Ptr
{
using MSXML2::IXMLDOMDocument2Ptr::IXMLDOMDocument2Ptr;
IXMLDOMDocument2Ptr* operator&(){return this;}
const IXMLDOMDocument2Ptr* operator&()const{return this;}
};
using CTest =
boost::multi_index_container<IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
{
// defined in scope so that destruction happens before CoUninitialize
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc));
}
::CoUninitialize();
return 0;
}
Would you mind entering a ticket for this problem at Boost Trac? I can fix the issue internally (by not relying on user-overloadable operator&s) but it's going to take a while till I find the time to do so and I wouldn't like to forget about it.
Postscript
If you have this problem throughout your program, you can automate the fix as follows:
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\random_access_index.hpp>
#include <boost\multi_index\global_fun.hpp>
#include <boost\multi_index\ordered_index.hpp>
#import "C:\Windows\SysWOW64\msxml6.dll" exclude("ISequentialStream", "_FILETIME")
template<typename CComPtr>
struct CFixedAddressofComPtr:CComPtr
{
using CComPtr::CComPtr;
CFixedAddressofComPtr* operator&(){return this;}
const CFixedAddressofComPtr* operator&()const{return this;}
};
template<typename CComPtr,typename TIndexList>
using CComPtrMultiIndexContainer=boost::multi_index_container<
CFixedAddressofComPtr<CComPtr>,
TIndexList
>;
using CTest =
CComPtrMultiIndexContainer<MSXML2::IXMLDOMDocument2Ptr,
boost::multi_index::indexed_by<boost::multi_index::random_access<>>>;
int main()
{
::CoInitialize(nullptr);
{
// declared in scope so that destruction happens before CoUninitialize.
CTest tst;
MSXML2::IXMLDOMDocumentPtr doc;
doc.CreateInstance(CLSID_DOMDocument);
tst.push_back(std::move(doc));
}
::CoUninitialize();
return 0;
}

multithreading - Asynchronous threads in class

I've got a class Foo, which have a main function and execute function. I want to start an unknown number of threads with the execute function, but when I try to compile the code I always get error C2064: term does not evaluate to a function taking 1 arguments.
foo.h
#ifndef BOT_H
#define BOT_H
#pragma once
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string>
class foo
{
public:
foo(char *_server, char *_port);
~foo(void);
private:
char *server;
char *port;
void execute(char *cmd);
void main();
};
#endif
foo.c
#include <thread>
#include "bot.h"
#include "definitions.h"
using namespace std;
foo::foo(char *_server, char *_port){
...
}
bot::~bot(void) {
...
}
void bot::execute(char *command){
...
}
void bot::main(){
thread(&bot::execute, (char*)commanda.c_str()).detach();
}
How should I create threads from class member functions?
Thanks for any answer
You need a bot object to call the member function on:
thread(&bot::execute, this, (char*)commanda.c_str())
^^^^
although you really should either change the function to take either std::string or const char*. You have a minefield of undefined behaviour here, if either the function tries to modify the string, or commanda is destroyed while the thread is still using it.
A lambda may be more readable; and would also fix the lifetime fiasco by capturing a copy of the string:
thread([=]{execute((char*)commanda.c_str();})

Visual Studio 2013 C++ - Passing std::unique_ptr to a bound function

Using Visual Studio 2013 RC and C++, I'm trying to pass an std::unique_ptr to a function that has been bound using std::bind. However, I'm having trouble because VS doesn't seem to like it when I try this. Here's what I'm trying to compile:
#include <memory>
#include <iostream>
#include <functional>
void func(std::unique_ptr<int> arg)
{
std::cout << *arg << std::endl;
}
int main()
{
std::function<void (std::unique_ptr<int>)> bound =
std::bind(&func, std::placeholders::_1);
std::unique_ptr<int> ptr(new int(42));
bound(std::move(ptr));
return 0;
}
This compiles in GCC 4.8.1, but not in VS2013 RC. I've always had problems with move semantics in VS, but I'd really like to use std::unique_ptr instead of std::shared_ptr or raw pointers.
One workaround I've found is to change the function signature to accept an std::unique_ptr&, which does compile in VS and GCC, but doesn't make the intent of func taking ownership of the std::unique_ptr particularly clear, and also prevents me from safely asynchronously calling the function unless I do something particularly ugly:
#include <memory>
#include <iostream>
#include <functional>
#include <future>
#include <string>
void func(std::unique_ptr<int>& arg)
{
std::cout << *arg << std::endl;
}
int main()
{
std::function<void (std::unique_ptr<int>&)> bound =
std::bind(&func, std::placeholders::_1);
std::unique_ptr<int> ptr(new int(42));
std::promise<void> prom;
std::async(
[&bound, &ptr, &prom]
{
std::unique_ptr<int> movedPtr = std::move(ptr);
prom.set_value();
bound(std::move(movedPtr));
});
prom.get_future().wait();
// Wait here
std::string dummy;
std::cin >> dummy;
}
Is there a way to get around this without changing func's signature?
Thanks!
I had the same problem with VS 2012 recently. I believe this is a bug in MSVC; at least in MSVC++11 the pseudo-variadic expansion seems to forward the parameters by value to some internal function. Seems this hasn't been improved.
As a workaround, I'm using lambdas instead, but another hack is required to make it work:
std::function<void (std::unique_ptr<int>)> bound =
[] (std::unique_ptr<int> arg) { func(std::move(arg)); };
still doesn't compile. But if you add any captured value (even one that isn't used), it compiles:
int x;
std::function<void (std::unique_ptr<int>)> bound =
[x] (std::unique_ptr<int> arg) { func(std::move(arg)); };
You have to move the parameter into the bound call to func also. Not only in the invocation of bound
bound(std::move(ptr));
but also in the binding:
std::function<void(std::unique_ptr<int>)> bound =
std::bind(func,
std::bind(std::move<std::unique_ptr<int>&>,
std::placeholders::_1));
This is compiling in VS2013 (update 4) for me.
Functions bound with std::bind do not forward arguments, it copies them to the function. As a result, std::bind doesn't work with move-only types as of c++11. This problem is the idea behind proposals for "more perfect forwarding" (like this one). There's a newer one, but I can't seem to find it right now.

Boost::Variant and function_types in it: How to put functions into Boost::variant?

Lyrics:
I try to implement a task pool over MPI. So I need some kind of RPC but one that would work between different parts of my program, meaning processor A wants processor B to call function C with argument D. We can not pass pointers to functions between processes like we do with threads, so we need some wrapper container to hold our function pointers at each process instance. All inside one source file\one program... So I started wondering about How to store functional objects with different signature in a container. My API Idea back then was wrong - it is better to define all functions in function pool at that pool construction (at least it shall be much easier to implement). But while implementing I faced next trouble:
Problem:
Such simple code (function_types, mpl::vector, variant):
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 0;
}
int main()
{
boost::variant<boost::function_types::function_type< boost::mpl::vector<int,int> >::type , boost::function_types::function_type< boost::mpl::vector<int,std::string> >::type > a;
return 0;
}
Will not compile falling with:
Error 1 error C2066: cast to function type is illegal c:\program files\boost\include\boost\variant\variant.hpp 1231 1
And looking at source we see:
this code block:
variant()
{
// NOTE TO USER :
// Compile error from here indicates that the first bound
// type is not default-constructible, and so variant cannot
// support its own default-construction.
//
new( storage_.address() ) internal_T0();
indicate_which(0); // zero is the index of the first bounded type
}
So I wonder: How to get around this error?
Also I tried:
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 1;
}
int main()
{
boost::variant< boost::function<int (std::string) >, boost::function<int (int) > > a;
a= &append<int>;
return 0;
}
Which fails with:
Error 1 error C2668: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : ambiguous call to overloaded function c:\program files\boost\include\boost\variant\variant.hpp 1330
Any Ideas on how to make boost.variant hold functions?
Of course we can play with shared pointers to functors like so:
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <string>
template <class in, class out>
struct s_append
{
out operator()(in val) {
std::cout << "hello";
return out();
}
};
int main()
{
boost::variant<boost::shared_ptr<s_append<int, int> >, boost::shared_ptr< s_append<std::string, int> > > a;
boost::shared_ptr<s_append<int, int> > b(new s_append<int, int> );
a=b;
return 0;
}
and it would compile but resulting API sucks - you have to 1) create functors for all functions you want to use (meaning limit there use of current process scope); 2) use shared_pointers and so I don't really even get how to call functions nested that way (simple first guess (*a)(22); just won't compile =( and API starts to be as bad as we would have using Boost.Any).
Try inserting a dummy type as the first argument of the variant. As the comment you found explains, only the first type in the variant is used for the variant's own default constructor. You could use an empty struct type for this (struct NoFunction {};).
That said, you may have been onto something with the idea to use boost::functions as the types in the variant...they are default-constructible at least. I'm not sure what the other error you had from that approach was caused by, but just wanted to let you know you could pursue that angle more if you can't use the dummy-type workaround I mentioned.