Problem: I have a class of parameters which I'm passing around as const Some_Class& param because these parameters aren't changing. I need to pass these parameters to external library (GSL) which is accepting void* param. I can't cast from const& to void*, except with using const_cast. I heared that const_cast is not generally right solution, is this the correct use case for it?
My solution: As a solution I'm now using wrapper structure
struct wrapper{const Some_class& param;};
void gsl_func(void* param){
const Some_class& my_param = static_cast<wrapper*>(param)->param;
}
void my_func(const Some_class& my_param){
wrapper my_wrapper = {my_param};
gsl_func(&my_wrapper);
}
Which doesn't seems like the most elegant solution as I have to do this before every call to GSL. Is there some standardize way how to do this better?
Related
I am implementing a command pattern implementations with large number of actions and parameters involved. To simplify I am planning to use class that can hold all possible params to module in a map.
class ParamBag {
public:
add(int paramId, shared_ptr<IParam> param);
bool contains(int paramId);
std::shared_ptr<IParam> get(paramId);
private:
int mask;
std::map<int, std::shared_ptr<IParam>> params;
};
One clear downside of this implementation is each param has to extend from IParam interface, can I somehow simplify this.
If the one that uses the param after the get knows the type of the param, then you can use c++17 std::any, or if you must use c++11 you can try boost::any, or if none of those you can resort back to a void*.
The difference is that void* will not fail on a cast to a wrong type, where any_cast would throw an exception, or return nullptr if used with a pointer. You would also need to use a custom deleter in the std::shared_ptr in order to be able to free the void*.
I want to achieve something like this:
class MyTest: public ::testing::Test {
public:
const int myConstInt = 23;
}
TEST_F(MyTest, MyTest1) {... use myConstInt ...}
But recollecting from Item 4 of EffectiveCPP, the initialization is not guaranteed in this manner and there is a chance of undefined behavior.
Let's say the above is Method 1.
I can think of two other methods to achieve this:
Method 2: Initializer list of myConstStr using a MyTest constructor.
Method 3: Make it constexpr - since the value is set at compile time I shouldnt face any initialization issues during runtime.
Which would be the correct way to go about this? Also Effective CPP is a relatively old book - Does the discussion of Item 4 still fully apply?
const int myConstInt = 23;
is a non static data member with a default member initializer
https://en.cppreference.com/w/cpp/language/data_members#Member_initialization
There is absolutely no risk that it is undefined behavior.
The initialization is guaranteed
Post discussion on Cpplang slack , found out that the best solution would be to use a static const for any integral/Enum types - can also use static constexpr but this is essentially the same except in C++17 where static constexpr data members can also be inlined.
Additioal useful Reference: constexpr vs. static const: Which one to prefer?
I have a function that is part of a class handles some input as pair of iterators. The signature of which is:
class Obj {
public:
template <typename InputIterator>
void handle_read(InputIterator first, InputIterator last);
...
};
I would like to bind that to a function:
void Obj::handle_connect() {
connections.start(std::make_shared<connection>(std::move(socket), connections, logger),
std::bind(&server::handle_read<InputIterator>, this, std::placeholders::_1, std::placeholders::_2));
}
However that doesn't work, specifically the error suggests that it can't find InputIterator.
However if I put the exact signature for the bind in:
std::bind(&server::handle_read<std::array<uint8_t, 8192>::iterator>, this, std::placeholders::_1, std::placeholders::_2));
It compiles, but the code is brittle: If I change to a vector then I will need to go around changing the signatures (though failing code will be easy to detect), and if I decide that a different container would be more efficient than an array in a particular use case, then it breaks altogether.
How I do keep the bind generic and not tied to a particular iterator type?
I want to specify that a certain type reported by Boost TypeIndex boost::typeindex::type_id<T>().pretty_name() would yield a specific name.
The problem I want to solve is that, as reported in other places, there is a particular case that is confusing, that is the std::string type (or alias) gets reported as std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >.
(I understand the reason for this, std::string is an alias. I just want to override the reported string in this particular case.)
I followed the instructions here http://www.boost.org/doc/libs/1_59_0/doc/html/boost_typeindex/making_a_custom_type_index.html and the beginning of the custom code looks like this:
namespace my_namespace { namespace detail {
template <class T> struct typenum;
template <> struct typenum<void>{ enum {value = 0}; };
template <> struct typenum<std::string>{ enum {value = 1}; };
struct my_typeinfo {const char* const type_;};
const my_typeinfo infos[2] = {
{"void"}, {"std::string"}
};
...
...
But at the end, the most I can do is to replace one type reporting by another, instead of just amending one case.
One light weight solution could be to specialize boost::typeindex::stl_type_index (the output type of type_id<std::string>()) but by then the actual static information of the class is lost. (there is no class to specialize.)
But this cannot be done without a full specialization of typeid<std::string> which seems to difficult to do.
Is there a workaround for this? I would prefer a solution within Boost.Typeindex rather than runtime string replacement.
This is a very dirty way I found but it is not perfect and can create other problems down the road.
struct std_string{}; // dummy replacement class name
namespace boost{
namespace typeindex{
template<> boost::typeindex::stl_type_index type_id<std::string>() noexcept{
return type_id<std_string>(); // will report "std_string", ugly, but better than `std::__cxx11::basic_string<...>`
}
}}
Problem:
Let's assume I have an algorithm that takes a unique_ptr to some type:
void FancyAlgo(unique_ptr<SomeType>& ptr);
Now I have shared_ptr sPtr to SomeType, and I need to apply the same algorithm on sPtr. Does this mean I have to duplicate the algorithm just for the shared_ptr?
void FancyAlgo(shared_ptr<SomeType>& sPtr);
I know smart pointers come with ownership of the underlying managed object on the heap. Here in my FancyAlgo, ownership is usually not an issue. I thought about stripping off the smart pointer layer and do something like:
void FancyAlgo(SomeType& value);
and when I need to call it with unique_ptr:
FancyAlgo(*ptr);
likewise for shared_ptr.
1, Is this an acceptable style in PRODUCTION code?(I saw somewhere that in a context of smart pointers, you should NOT manipulate raw pointers in a similar way. It has the danger of introducing mysterious bugs.)
2, Can you suggest any better way (without code duplication) if 1 is not a good idea.
Thanks.
Smart pointers are about ownership. Asking for a smart pointer is asking for ownership information or control.
Asking for a non-const lvalue reference to a smart pointer is asking for permission to change the ownership status of that value.
Asking for a const lvalue reference to a smart pointer is asking for permission to query the ownership status of that value.
Asking for an rvalue reference to a smart pointer is being a "sink", and promising to take that ownership away from the caller.
Asking for a const rvalue reference is a bad idea.
If you are accessing the pointed to value, and you want it to be non-nullable, a reference to the underlying type is good.
If you want it to be nullable, a boost::optional<T&> or a T* are acceptable, as is the std::experimental "world's dumbest smart pointer" (or an equivalent hand-written one). All of these are non-owning nullable references to some variable.
In an interface, don't ask for things you don't need and won't need in the future. That makes reasoning about what the function does harder, and leads to problems like you have in the OP. A function that reseats a reference is a very different function from one that reads a value.
Now, a more interesting question based off yours is one where you want the function to reseat the smart pointer, but you want to be able to do it to both shared and unique pointer inputs. This is sort of a strange case, but I could imagine writing a type-erase-down-to-emplace type (a emplace_sink<T>).
template<class T>
using later_ctor = std::function<T*(void*)>;
template<class T, class...Args>
later_ctor<T> delayed_emplace(Args&&...args) {
// relies on C++1z lambda reference reference binding, write manually
// if that doesn't get in, or don't want to rely on it:
return [&](void* ptr)->T* {
return new T(ptr)(std::forward<Args>(args));
};
}
namespace details {
template<class T>
struct emplace_target {
virtual ~emplace_target() {}
virtual T* emplace( later_ctor<T> ctor ) = 0;
};
}
template<class T>
struct emplacer {
std::unique_ptr<emplace_target<T>> pImpl;
template<class...Args>
T* emplace( Args&&... args ) {
return pImpl->emplace( delayed_emplace<T>(std::forward<Args>(args)...) );
}
template<class D>
emplacer( std::shared_ptr<T, D>& target ):
pImpl( new details::emplace_shared_ptr<T,D>(&target) ) // TODO
{}
template<class D>
emplacer( std::unique_ptr<T, D>& target ):
pImpl( new details::emplace_unique_ptr<T,D>(&target) ) // TODO
{}
};
etc. Lots of polish needed. The idea is to type-erase construction of an object T into an arbitrary context. We might need to special case shared_ptr so we can call make_shared, as a void*->T* delayed ctor is not good enough to pull that off (not fundamentally, but because of lack of API hooks).
Aha! I can do a make shared shared ptr without special casing it much.
We allocate a block of memory (char[sizeof(T)]) with a destructor that converts the buffer to T then calls delete, in-place construct in that buffer (getting the T*), then convert to a shared_ptr<T> via the shared_ptr<T>( shared_ptr<char[sizeof(T)]>, T* ) constructor. With careful exception catching this should be safe, and we can emplace using our emplacement function into a make_shared combined buffer.