Static casting to unique_ptr - c++11

I have a head file which needs to hide some internals for complexity and "secrecy" reasons. I've therefore a raw void pointer declared in the oublic header, inside the code there are static casts to convert the raw pointer to it's actual type.
Now due to general memory management changes I need to change the type internally to a unique_ptr (it's coming from an object factory now as a unique_ptr, previously it was a raw pointer).
So in my header I have this:
class SomeClass {
private:
void *_hiddenTypeInstance;
}
Is it possible to static-cast this _hiddenTypeInstance to an internally known unique_ptr type?

This is not a direct answer of what you wanted, but a proposal how to do things nicer:) You can actually still use the memory semantics of std::unique_ptr with hiding the internals and without using the ugly void*. As others have mentioned, you should look into PIMPL, but to summarize:
Forward declare the internal type in the public header
Use std::unique_ptr with that type and provide a dtor for the class which holds that member (otherwise you will get compilation errors because a default dtor will be generated, that will try to delete the forward declared class and will fail to do so).
This would look something like this:
#include <memory>
class CPrivate; // Forward declare the internal class
class CPublic
{
public:
// You need the dtor here, since when you implement it in the .cpp of your library,
// where the definition of CPrivate is known, the dtor of std::unique_ptr will know how to delete it.
// If you do not put the dtor here, a default one will be generated here which invokes the dtor of std::unique_ptr, and here
// since CPrivate is forward declared the dtor of std::unique_ptr will not know how to delete it and you will get an error
~CPublic();
private:
std::unique_ptr<CPrivate> m_pPrivate;
}
By using this, you can then escape the casts inside the implementation from the void* to the actual type.
As for the original question - you can always cast void* to a std::unique_ptr<T>* (a pointer to a unique_ptr). But I would advise to evaluate the solution above. Because the void* thing moves away all type strictness - e.g what happens if someone changes T ?

if i understand you problem in a correct way: here is what you can do. This example is just for understanding of a concept. You can use it in your own code. Since I dont have the entire code I cant write exact solution.
class SomeClass {
private:
void *_hiddenTypeInstance;
public:
std::unique_ptr<int> foo() {
int a;
a = 2;
return std::unique_ptr<int>(&a);
}
void bar() {
std::unique_ptr<int> temp_hidden_type_instance;
temp_hidden_type_instance = std::unique_ptr<int>(static_cast<int*>(_hiddenTypeInstance));
temp_hidden_type_instance = foo();
}
};

Related

When initializing an atomic class member it requires a 'deleted' function, but adding it would make it no longer trivially copyable

When initializing an atomic class member it requires a 'deleted' function, but adding it would make it no longer trivially copyable which is a requirement for an object/struct to be atomic. Am I just not understanding how to do this correctly, or is this a problem in the c++ standard?
Take the example below:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
Trying to compile this with g++ gives error: use of deleted function 'A<int>::A(const A<int>&)' myA.store(a, std::memory_order_relaxed);. My understanding of this error is that the atomic::store method is looking for that constructor in my struct A but not finding it.
Now here is what happens when I add that constructor:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
A(const A<T>& obj) { }
A( ) { }
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
I no longer receive the above compiler error but a new one coming from the requirements of the atomic class required from 'class B<int>' .... error: static assertion failed: std::atomic requires a trivially copyable type ... In other words by adding the used-defined constructors I have made my struct A a non-trivially copyable object which cannot be initialized in class B. However, without the user-defined constructors I cannot use the store method in myA.store(a, std::memory_order_relaxed).
This seems like a flaw in the design of the std::atomic class. Now maybe I am just doing something wrong because I don't have a lot of experience using C++11 and up (I'm old school). Since 11 there have been a lot of changes and the requirements seem to be a lot stricter. I'm hoping someone can tell me how to achieve what I want to achieve.
Also I cannot change std::atomic<A<T>> myA; to std::atomic<A<T>> * myA; (changed to pointer) or std::atomic<A<T>*> myA;. I realize this will compile but it will destroy the fundamental design of a class I am trying to build.
The problem here resides in the fact that std::atomic requires a trivially copiable type. This because trivially copyable types are the only sure types in C++ which can be directly copied by copying their memory contents directly (eg. through std::memcpy). Also non-formerly trivially copyable types could be safe to raw copy but no assumption can be made on this.
This is indeed important for std::atomic since copy on temporary values is made through std::memcpy, see some implementation details for Clang for example.
Now at the same time std::atomic is not copy constructible, and this is for reasonable reasons, check this answer for example, so it's implicitly not trivially copyable (nor any type which contains them).
If, absurdly, you would allow a std::atomic to contain another std::atomic, and the implementation of std::atomic contains a lock, how would you manage copying it atomically? How should it work?

Why does making this virtual destructor inline fix a linker issue?

If I have a pure virtual class InterfaceA that consists solely of a pure virtual destructor, why do I have to define the destructor as inline? I I don't I get an error when I try to link it.
Below is an admittedly contrived example, however it illustrates the point. The point does not compile for me using cmake and g++. However, if I change the InterfaceA destructor definition as follows - inline InterfaceA::~InterfaceA(){}; then it compiles.
Why is this? What does the inline keyword do?
// InterfaceA.h, include guards ommitted for clarity
class InterfaceA
{
public:
virtual ~InterfaceA() = 0;
};
InterfaceA::~InterfaceA(){};
// A.h, include guards ommitted for clarity
#include "InterfaceA.h"
class A : public InterfaceA
{
public:
A(int val)
: myVal(val){};
~A(){};
int myVal;
};
// AUser.h, include guards ommitted for clarity
#include "InterfaceA.h"
class AUser
{
public:
AUser(InterfaceA& anA)
: myA(anA){};
~AUser(){};
int getVal() const;
private:
InterfaceA& myA;
};
// AUser.cpp
#include "AUser.h"
#include "A.h"
int AUser::getVal() const
{
A& anA = static_cast<A&>(myA);
return anA.myVal;
}
// main.cpp
#include "AUser.h"
#include "A.h"
#include <iostream>
int main(){
A anA(1);
AUser user(anA);
std::cout << "value = " << user.getVal() << std::endl;
return 0;
}
You have to use the inline keyword when defining functions in header files. If you do not, and the file is included in more than one translation unit, the function will be defined twice (or more times).
The linker error is probably something like "Symbol ... is multiply defined" right?
If you defined the member function in the body of the class, it would be implicitly inline and it would also work.
See this answer
To answer the question "What does the inline keyword do?":
In the old days it would be used to ask the compiler to inline functions i.e. insert the code whenever the function is used instead of adding a function call. Eventually it turned into a simple suggestion since compiler optimizers became more knowledgeable about which functions were inline candidates. These days it is used almost exclusively to define functions in header files that must have external linkage.
inline means that compiler is allowed to add code directly to where the function was called. It also removes function from external linkage, so both your compile units would have local version of.. pure destructor.
// InterfaceA.h, include guards ommitted for clarity
class InterfaceA
{
public:
virtual ~InterfaceA() = 0;
};
You declare destructor virtual, so compiler almost never would make it inline. Why? because virtual functions are called through vtable - a internal working of virtual functions system, vtable most likely implemented as an array of pointers to member functions. If function is inlined, it would have no address, no legal pointer. If attempt to get address of function is taken, then compiler silently disregards inline keyword. The other effect will be still in place: inlined destructor stops to be visible to linker.
It may look like declaring pure virtual destructor looks like oxymoron , but it isn't. The pure destructor is kind of destructor that would be always called without causing UB. Its presence would make class abstract, but the implicit call in sequence of destructor calls would still happen. If you didn't declare destructor body, it would lead to an UB, e.g. purecall exception on Windows.
If you don't need an abstract base class, then inline definition will suffice:
class InterfaceA
{
public:
virtual ~InterfaceA() {}
};
that is treated by compiler as inline as well, but mixing inline definition and pure member declaration is not allowed.

Where should a default destructor C++11 style go, header or cpp?

In C++11 a default implementation of constructor(s), destructor and copy/move operators can be specified with "= default". Where to put the "= default", in header file, where the class definition is, or in the source file (cpp)?
In header file Test.h:
class Test
{
public:
~Test() = default;
};
In source file Test.cpp:
class Test
{
public:
~Test();
};
#include "Test.h"
Test::~Test() = default;
I have to disagree with rubenvb. You aren't forced to put the explicit default destructor in the header file.
In fact, there is a use case for which it's perfectly valid (and necessary) to put the explicit default destructor in the .cpp file.
Consider the case where you forward declare a class in the header file, and use it with one of the smart pointers templates. As the implicit destructor doesn't have the complete declaration of the forward declared class, it cannot properly do its deletion. Therefore, you need to move the destructor definition to the C++ file, where you should have access to the complete declaration.
In A.hpp:
#pragma once
#include <memory>
class B;
class A
{
private:
std::unique_ptr<B> my_b;
public:
// ~A() = default;
// defining the default destructor would fail as
// class B is still a partial class here
~A();
};
In A.cpp:
#include "A.hpp"
// the previously forward declared class B is now included here
#include "B.hpp"
// we can use the default destructor here as B is
// no longer a partial class
A::~A() = default;
You can do both:
in the first case (header) the destructor will be considered as non-user defined
in the second case (cpp) the compiler will consider it as user defined.
A user-provided destructor is non-trivial, making the class itself necessarily non-trivial.
Unless you have a good reason to for the second option, putting it in the header is the usual way to go.
You must put it in the header (well, wherever the class definition is located and the destructor is declared) or else anyone using your class won't know about this behaviour, including the compiler, which leads to obvious wrong behaviour on its part.

can std::forward takes std::function<void()> as the class type?

I've always seen std::forward being utilized as below, utilized inside a template function
template<class T>
void foo(T&& arg): bar(std::forward<T>(arg)){}
Suppose I want to do this.
class A
{
private:
std::function<void()> bar;
public:
template<class T>
A(T&& arg):
bar(std::forward<T>(arg))
{}
};
Since bar already has its type defined. I can also directly specify T as std::function<void()> >.
class A
{
private:
std::function<void()> bar;
public:
A(std::function<void()>&& arg):
bar(std::forward<std::function<void()>>(arg))
{}
};
Both would be ok to compile. However, the second realization only support A(const std::function<void()>). While the first realization support A(const std::function<void()>&) and A(std::function<void()>&&) etc.
Forward is a conditional move of its argument. It is almost equivalent to std::move if and only if the type passed to it is a value type or rvalue reference type.
A move is a cast to an rvalue reference.
If you pass a different type to std::forward than its argument type, it will do horrible things. If convertible between, this would often involve creating a temporary within a function then returning a reference to it.
The proper thing to pass to std::forward(x) is X, where the type of x is X&&. Anything else is going to be extremely quirky and advanced use, and will probably cause unexpected behavior...
In your case, the second works fine, but is pointless. As std::forward is a conditional move, and we are passing it a fixed type, we know it is a std::move.
So we should replace std::forward<std::function<void()>>(arg) with std::move(arg), which is both clearer and more conventional. Also, equivalent in this case.
Generally std::forward should only be used in cases where you are using forwarding references.

How do I get the method pointer of a class, with multiple implementations of that method?

#include <cstdio>
struct A {
void foo(int) { printf("this is the wrong function\n"); }
void foo() { printf("this is the right function\n"); }
};
int main() {
auto method = &A::foo; // c++ why don't you me allow to give argument types?
A a;
(a.*method)();
}
I know this little example works fine with just replacing auto with an explicit type, but that is not, what I am looking for. I would like to tell c++ on the right side of the equals, which method I want.
The compiler cannot guess which method you refer to unless you specify which overload you are interested in, by explicitely writing its prototype. You can do that either by explicitely typing your variable, like you said:
void (A::*foo)() = &A::foo;
void (A::*fooInt)(int) = &A::foo;
Or you can use a cast on the right hand side of the initialization:
auto foo = static_cast<void (A::*)()>(&A::foo);
auto fooInt = static_cast<void (A::*)(int)>(&A::foo);
You can't use auto here, as it would be ambiguous. You need to explicitly type your variable or use a cast on the right-hand side to restrict the matching to only one of the two candidates.

Resources