Is this use of reinterpret_cast undefined behaviour? - c++

I'm not sure about this piece of code:
#include <functional>
#include <list>
#include <iostream>
void f() { std::cout << "HI!\n"; }
struct fobj
{
void operator()() const { std::cout << "Bye!\n"; }
};
using slot_t = std::function<void()>;
std::list<slot_t> slot_list;
template<class F>
inline std::size_t insert_slot(F f)
{
auto it = slot_list.insert(slot_list.begin(), f);
return reinterpret_cast<std::size_t>(&*it);
}
inline slot_t& recover_slot(std::size_t conn_id)
{ return *reinterpret_cast<slot_t*>(conn_id); }
int main()
{
std::size_t conn1_id = insert_slot(f);
std::size_t conn2_id = insert_slot(fobj());
recover_slot(conn1_id)(); // HI!
recover_slot(conn2_id)(); // Bye!
}
I don't see the reinterpret_cast<T*>(some_size_t) any different from static_cast<T*>(some_void_ptr), but I'm not really sure how risky the former is.

Related

Make int overload a preferable one

Consider following code snippet:
class Foo {
public:
void bar(std::size_t){}
void bar(const char* ){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
It produces ambiguous calls errors (check here). But I think from programmer's perspective it is pretty obvious that I want to call overload with std::size_t. My question is if anything can be done so this code does not produce errors and calls size_t overload?
can be done like this in C++ 20
#include <cstdint>
#include <iostream>
#include <type_traits>
class Foo {
public:
template <typename T>
requires std::is_integral_v<T>
void bar(T){
std::cout<<"hello size_T";
}
void bar(const char* ){
std::cout<<"hello";
}
};
int main() {
auto foo = Foo{};
foo.bar(25);
}
In modern c++ (at least c++17), we prefer to pass string_view as argument over const char* for the none owner transfer cases, so a considerable choice:
#include <cctype>
#include <string>
class Foo {
public:
void bar(std::size_t){}
void bar(std::string_view){}
};
int main() {
auto foo = Foo{};
foo.bar(0);
}
Online demo
In below C++ 20, this works well.
#include <iostream>
class Foo {
public:
template <typename T>
void bar(T) {
std::cout << "hello T" << std::endl;
}
void bar(const char* c) {
std::cout << c << std::endl;
}
};
int main() {
auto foo = Foo{};
foo.bar(0);
foo.bar("test.");
}
This works in C++23:
foo.bar(0zu);
and this works pre-C++23:
foo.bar(size_t{0});

boost asio timer wrapped in coroutines causes SEGFAULT on clang-5.0

Following code causes SEGFAULT on clang-5.0 with enabled coroutines support.
You can run the code online here:
wandbox compiled code
I am using compiler options:
-stdlib=libc++ -fcoroutines-ts
When I run it under GDB it SEGFAULTs in async_await after coro.resume(); is called.
await_resume function is never reached.
I expect this to be an object lifetime issue. Very much same piece of code compiles and runs under MSVC 2017 without any issues.
The output of the program is:
i=0
Segmentation fault
Finish
Source code:
#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION // Enables future::then
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/asio/system_timer.hpp>
#include <experimental/coroutine>
#include <chrono>
#include <iostream>
namespace std
{
namespace experimental
{
template <typename... Args>
struct coroutine_traits<boost::future<void>, Args...> {
struct promise_type {
boost::promise<void> p;
auto get_return_object() { return p.get_future(); }
std::experimental::suspend_never initial_suspend() { return {}; }
std::experimental::suspend_never final_suspend() { return {}; }
void unhandled_exception(){}
void return_void() { p.set_value(); }
};
};
}
}
namespace asioadapt
{
using namespace std::experimental;
template <typename R> auto operator co_await(boost::future<R> &&f) {
struct Awaiter {
boost::future<R> &&input;
boost::future<R> output;
bool await_ready() { return false; }
auto await_resume() { return output.get(); }
void await_suspend(std::experimental::coroutine_handle<> coro) {
input.then([this, coro](auto result_future) mutable{
this->output = std::move(result_future);
coro.resume();
});
}
};
return Awaiter{ static_cast<boost::future<R>&&>(f) };
}
template <typename R, typename P>
auto async_await(boost::asio::system_timer &t, std::chrono::duration<R, P> d) {
struct Awaiter
{
boost::asio::system_timer &t;
std::chrono::duration<R, P> d;
boost::system::error_code ec;
bool await_ready() { return false; }
void await_suspend(std::experimental::coroutine_handle<> coro) {
t.expires_from_now(d);
t.async_wait([this, &coro](auto ec) mutable {
this->ec = ec;
coro.resume();
});
}
void await_resume() {
if (ec)
throw boost::system::system_error(ec);
}
};
return Awaiter{ t, d };
}
}
using namespace boost;
using namespace boost::asio;
using namespace std::chrono_literals;
using namespace asioadapt;
boost::future<void> sleepy(io_service &io, int &i) {
system_timer timer(io);
std::cout << "i=" << i << std::endl;
co_await async_await(timer, 100ms);
++i;
std::cout << "i=" << i << std::endl;
co_await async_await(timer, 100ms);
++i;
std::cout << "i=" << i << std::endl;
co_await async_await(timer, 100ms);
++i;
std::cout << "i=" << i << std::endl;
}
void test(){
int i = 0;
io_service io;
auto future = sleepy(io, i);
io.run();
std::cout << "i=" << i << std::endl;
}
int main()
{
test();
}
I have overlooked the & in lambda capture await_suspend function. So the coroutine_handle is destroyed after this call.

C++ templated class default constructor fails

So I am creating a Stack class for an assignment in C++. The core of the assignment is to familiarize us with templates. I have read my book over and over and looked question after question on here.
I need to have my Stack class be able to be constructed by
Stack s2;
but I get an error when I compile my test.cpp and can only compile when i construct as
Stack<T> s1;
where T is a std::string, int, etc. How do build my Stack so I can use both constructors?
Stack.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
using namespace std;
template<typename T>
class Stack {
public:
Stack();
void Push(T val);
T Pop();
void Print();
private:
vector<T> vecT;
};
template <typename T>
Stack<T>::Stack() { }
template <typename T>
void Stack<T>::Push(T val) { vecT.push_back(val); }
template <typename T>
T Stack<T>::Pop() { vecT.pop_back(); }
template <typename T>
void Stack<T>::Print() {
cout << "[ ";
for(int i=0; i<vecT.size(); i++) {
cout << vecT[i] << " ";
}
cout << "]";
}
test.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
#include "Stack.cpp"
using namespace std;
int main() {
Stack<string> s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
What about a default template parameter?
template<typename T = std::string>
class Stack {
Anyway, with
Stack<T> s1;
and
Stack s2;
you're not using different constructors; you're using, in both cases, the same default (no arguments) constructor.
Instead of templating everything you could just use a stack of a variant type (since C++17, before use Boost.Variant). With the code below you can now push int, double, and std::string onto the stack. Furthermore, Pop() is missing a return statement. Also, pop_back() of vector returns nothing.
#include <iostream>
#include <vector>
#include <string>
#include <variant>
class Stack {
using Variant = std::variant<int,double,std::string>;
public:
Stack();
void Push(Variant val);
void Pop();
void Print();
private:
std::vector<Variant> vecT;
};
Stack::Stack() : vecT() {}
void Stack::Push(Variant val) { vecT.push_back(val); }
void Stack::Pop() { vecT.pop_back(); }
void Stack::Print() {
std::cout << "[ ";
for ( auto const& v : vecT )
std::visit([] (auto&& arg) { std::cout << arg << " "; }, v);
std::cout << "]\n";
}
int main() {
Stack s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
With Boost.Variant you get a C++98 compatible solution.
#include <iostream>
#include <vector>
#include <string>
#include <boost/variant.hpp>
class Stack {
typedef boost::variant<int,double,std::string> Variant;
typedef std::vector<Variant>::iterator Iterator;
std::vector<Variant> vecT;
struct visitor : public boost::static_visitor<void>
{
template < typename T >
void operator()(T const& arg) const { std::cout << arg << " "; }
};
public:
Stack();
void Push(Variant val);
void Pop();
void Print();
};
Stack::Stack() : vecT() {}
void Stack::Push(Variant val) { vecT.push_back(val); }
void Stack::Pop() { vecT.pop_back(); }
void Stack::Print() {
std::cout << "[ ";
for ( Iterator it = vecT.begin(); it != vecT.end(); ++it )
boost::apply_visitor( visitor(), *it );
std::cout << "]\n";
}
int main() {
Stack s1;
s1.Push("values1");
s1.Push("values2");
s1.Print();
Stack s2;
s2.Push("values1");
s2.Push("values2");
s2.Print();
}
You could use a default template parameter:
template<typename T = int>
class Stack {
Then you could construct using:
Stack<> s2;
Also, the constructors are identical, you aren't calling a different one each time, but rather the template argument differs.

Container that will store any elements pushed in it for certain period of time

I need to have a container that will store any elements pushed in it for 10 minutes. How can I do it? Should I use something like boost::deadline_timer for such purpose?
I've tried to write the following code:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time.hpp>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <map>
#include <utility>
namespace koicxx {
template <typename T>
class temp_storage : private boost::noncopyable
{
typedef boost::shared_ptr<boost::asio::deadline_timer> shared_timer_t;
typedef std::map<T, shared_timer_t> timer_map_t;
typedef std::pair<T, shared_timer_t> timer_pair_t;
typedef boost::function<void(const T&, const boost::system::error_code&)> callback_t;
public:
temp_storage(boost::asio::io_service& io_service) :
_io_service(io_service) {}
bool add(const T& element, const boost::asio::deadline_timer::duration_type& timeout, callback_t callback = callback_t())
{
boost::lock_guard<boost::mutex> lock(_sync);
const std::pair<timer_map_t::iterator, bool>& res =
_internal_storage.insert(
timer_pair_t(
element
, shared_timer_t(new boost::asio::deadline_timer(_io_service, timeout))
));
if (!res.second)
{
return false;
}
const timer_map_t::iterator& itr = res.first;
if (callback)
{
itr->second->async_wait(
boost::bind(
callback
, itr->first
, boost::asio::placeholders::error
));
}
itr->second->async_wait(
boost::bind(
&temp_storage::remove_callback
, this
, itr->first
, boost::asio::placeholders::error
));
return true;
}
bool remove(const T& element)
{
boost::lock_guard<boost::mutex> lock(_sync);
const timer_map_t::iterator& itr = _internal_storage.find(element);
if (itr == _internal_storage.end())
{
return false;
}
itr->second->cancel();
_internal_storage.erase(itr);
return true;
}
bool contains(const T& element)
{
boost::lock_guard<boost::mutex> lock(_sync);
return _internal_storage.find(element) != _internal_storage.end();
}
void clear()
{
boost::lock_guard<boost::mutex> lock(_sync);
for (timer_map_t::value_type& i : _internal_storage)
{
i.second->cancel();
}
_internal_storage.clear();
}
private:
void remove_callback(const T& element, const boost::system::error_code& e)
{
if (e == boost::asio::error::operation_aborted)
{
return;
}
remove(element);
}
boost::asio::io_service& _io_service;
timer_map_t _internal_storage;
boost::mutex _sync;
};
} // namespace koicxx
int main()
{
boost::asio::io_service io_service;
io_service.run();
koicxx::temp_storage<int> some_storage(io_service);
some_storage.add(0, boost::posix_time::seconds(2));
some_storage.add(1, boost::posix_time::seconds(3));
some_storage.add(2, boost::posix_time::seconds(5));
while (true)
{
if (some_storage.contains(0))
{
std::cout << 0 << ' ';
}
if (some_storage.contains(1))
{
std::cout << 1 << ' ';
}
if (some_storage.contains(2))
{
std::cout << 2 << ' ';
}
std::cout << '\n';
boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
}
But it doesn't work as expected -- it gives "0 1 2" output all time. Why? What am I doing wrong? How can I fix it?
Maybe this can help you.
#include <vector>
#include <memory>
#include <chrono>
#include <algorithm>
#include <string>
using timepoint = std::chrono::time_point<std::chrono::system_clock>;
//type erasure code
struct Holder{
virtual timepoint getCreationTime() const = 0;
virtual ~Holder(){}
};
template <class T>
struct HolderHelper : Holder{
HolderHelper(std::unique_ptr<T> &&up, timepoint t = timepoint::clock::now()) :
object(std::move(up)), creationtime(t){}
std::unique_ptr<T> object;
timepoint creationtime;
timepoint getCreationTime() const final override{
return creationtime;
}
};
//convenience wrapper
//it can be made more convenient if you limit yourself to movable objects
template <class T>
std::unique_ptr<Holder> make_timed_holder(std::unique_ptr<T> &&up){
return std::unique_ptr<Holder>(new HolderHelper<T>(std::move(up)));
}
template <class T>
std::unique_ptr<Holder> make_timed_holder(std::unique_ptr<T> &&up, timepoint t){
return std::unique_ptr<Holder>(new HolderHelper<T>(std::move(up), t));
}
//usage
int main(){
//using a vector as a container, can be any other container
std::vector<std::unique_ptr<Holder>> v;
//inserting different objects
v.push_back(make_timed_holder(std::make_unique<int>(42)));
v.push_back(make_timed_holder(std::make_unique<std::string>("Hello")));
v.push_back(make_timed_holder(std::make_unique<std::vector<std::vector<std::string>>>()));
//removing all objects that have run out of time
/* for a sequence container the outdated objects are always in the front,
so you can make the search faster
For a set you can use the creation time as a key and make it search quicker that way
*/
auto now = timepoint::clock::now();
v.erase(std::remove_if(begin(v), end(v), [&](std::unique_ptr<Holder> &u){
return u->getCreationTime() + std::chrono::minutes(10) < now;
}), end(v));
}
You may need to implement your own make_unique.

Storing function pointer in std::function

I'm trying to write a C++0x wrapper around dlopen()/dlsym() to dynamically load functions from shared objects:
class DynamicLoader
{
public:
DynamicLoader(std::string const& filename);
template<class Signature>
std::function<Signature> load(std::string const& functionName);
private:
void *itsLibraryHandle;
};
DynamicLoader::DynamicLoader(std::string const& filename)
{
itsLibraryHandle = dlopen(filename.c_str(), RTLD_LAZY);
if(!itsLibraryHandle)
{ /* Throw Some Error */ }
}
template<class Signature>
std::function<Signature> DynamicLoader::load(std::string const& functionName)
{
return <insert magic here> dlsym(itsHandle, functionName.c_str());
}
Is there a way to convert the void* function pointer returned by dlsym into a std::function?
try this:
static_cast<Signature*>()
seems works in VC10
complete test:
#include <functional>
void test()
{}
template <typename Signature>
std::function<Signature> cast(void* f)
{
return static_cast<Signature*>(f);
}
int main()
{
std::function<void()> f = cast<void()>(&test);
return 0;
}
Based on what I see here: http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_pointer.hpp>
template< typename Signature >
std::function<Signature> DynamicLoader::load(std::string const& name)
{
namespace ft = boost::function_types;
typedef typename ft::function_pointer< typename ft::components<Signature>::type >::type fp_t;
fp_t fun_ptr;
*reinterpret_cast<void**>(&fun_ptr) = dlsym(itsHandle, name.c_str());
return fun_ptr;
}
I've never used dlsym so I don't understand why the cast is being done that way and not simply casting dlsym's return like so:
fun_ptr = reinterpret_cast<fp_t>(dlsym(itsHandle, name.c_str());
You just need to cast result of dlsym() call to a proper type. Here's a complete working example:
#include <functional>
#include <iostream>
#include <stdexcept>
#include <string>
#include <dlfcn.h>
class DynamicLoader
{
public:
DynamicLoader(std::string const& filename) :
m_handle(dlopen(filename.c_str(), RTLD_LAZY))
{
if (!m_handle)
{
throw std::logic_error("can't load library named \"" + filename + "\"");
}
}
template<class T>
std::function<T> load(std::string const& functionName) const
{
dlerror();
void* const result = dlsym(m_handle, functionName.c_str());
if (!result)
{
char* const error = dlerror();
if (error)
{
throw std::logic_error("can't find symbol named \"" + functionName + "\": " + error);
}
}
return reinterpret_cast<T*>(result);
}
private:
void* const m_handle;
};
int main()
{
DynamicLoader const loader("/lib64/libz.so.1");
auto const zlibVersion = loader.load<char const* (void)>("zlibVersion");
std::cout << "zlib version: " << zlibVersion() << std::endl;
return 0;
}