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

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?

Related

C++ Check if generic object has member function matching signature

first post, so hopefully not violating any etiquette. Feel free to give suggestions for making the question better.
I've seen a few posts similar to this one: Check if a class has a member function of a given signature, but none do quite what I want. Sure it "works with polymorphism" in the sense that it can properly check subclass types for the function that comes from a superclass, but what I'd like to do is check the object itself and not the class. Using some (slightly tweaked) code from that post:
// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
static_assert(integral_constant<T, false>::value,
"Second template parameter needs to be of function type."
);
};
template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {
template<typename T>
static constexpr auto check(T*) -> typename is_same<
decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;
template<typename>
static constexpr false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};
I'd like to have something like the following:
// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
if (HasFunction<T, int(double)>::value)
cout << "Found it!" << endl;
// Do something with obj.myfunc
else cout << "Nothin to see here" << endl;
}
int main()
{
Y y;
W* w = &y; // same object
DoSomething(y); // Found it!
DoSomething(*w); // Nothin to see here?
}
The problem is that the same object being viewed polymorphically causes different results (because the deduced type is what is being checked and not the object). So for example, if I was iterating over a collection of W*'s and calling DoSomething I would want it to no-op on W's but it should do something for X's and Y's. Is this achievable? I'm still digging into templates so I'm still not quite sure what's possible but it seems like it isn't. Is there a different way of doing it altogether?
Also, slightly less related to that specific problem: Is there a way to make HasFunction more like an interface so I could arbitrarily check for different functions? i.e. not have ".myfunc" concrete within it? (seems like it's only possible with macros?) e.g.
template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
Bar b;
if(HasFoo<b>::value) b.foo();
}
Obviously that's invalid syntax but hopefully it gets the point across.
It's just not possible to perform deep inspection on a base class pointer in order to check for possible member functions on the pointed-to type (for derived types that are not known ahead of time). Even if we get reflection.
The C++ standard provides us no way to perform this kind of inspection, because the kind of run time type information that is guaranteed to be available is very limited, basically relegated to the type_info structure.
Your compiler/platform may provide additional run-time type information that you can hook into, although the exact types and machinery used to provide RTTI are generally undocumented and difficult to examine (This article by Quarkslab attempts to inspect MSVC's RTTI hierarchy)

Passing an unspecialised template to another template

Given the following code here in IDEOne:
#include <iostream>
#include <vector>
#include <list>
template<typename T>
class MyVectorCollection
{
using collection = std::vector<T>;
};
template<typename C, typename T>
class MyGenericCollection
{
using collection = C;
};
template<typename C, typename T>
class MyMoreGenericCollection
{
using collection = C<T>;
};
int main() {
// your code goes here
MyVectorCollection<int> a;
MyGenericCollection<std::list<int>, int> b;
MyMoreGenericCollection<std::list, int> c; // How to do this?
return 0;
}
I get the error:
prog.cpp:20:24: error: ‘C’ is not a template
using collection = C<T>;
^
prog.cpp: In function ‘int main()’:
prog.cpp:27:43: error: type/value mismatch at argument 1 in template parameter list for ‘template<class C, class T> class MyMoreGenericCollection’
MyMoreGenericCollection<std::list, int> c;
^
prog.cpp:27:43: note: expected a type, got ‘list’
How can I write my code such that I can use a C<T> at compile time without having an explicit list of potential specialisations, and avoiding macros, if possible? I realise std::list isn't a typename, but I don't know how to progress, and I have been unable to find a similar question here.
(Note that this is just an MCVE, my actual usage is much more involved.)
Just to tidy up, here is the solution. The search term I was looking for is template template, and whilst I did find a possible duplicate, I think this question and answer is much simpler to follow.
So, thanks to the hint from #Some programmer dude, I looked up template template and updated the code to this, which does compile:
template<template<typename, typename> class C, typename T>
class MyMoreGenericCollection
{
using collection = C<T, std::allocator<T>>;
};
We declare the first template parameter as a template itself, and remembering that the standard library constructors take two parameters, we need to make the inner template take two parameters. There is (as far as I am aware) no way to automatically use the default second parameter, so for the sake of this example I explicitly state the default.
I could of course add a third parameter to the master template that could be used to specify the allocator, which itself would also be a template, but I leave that as an exercise for th reader.

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.

Correct way of initializing a unique_ptr

Working on learning how to use smart pointers and C++ in general... Assume that I have the following class:
template<typename T>
class MyClass {
public:
MyClass(const T& def_val)
private:
std::unique_ptr<T> default_val;
};
What is the idiomatic way of implementing the constructor if I would only like to store a pointer to an object of type T with the value given in the default_val class member? My understanding is also that I don't have to define a destructor at all, since the unique_ptr will automatically taking care of cleaning up itself?
The way you have written your code, MyClass can only store a unique pointer to a copy of the constructor parameter:
MyClass::MyClass(const T& def_val)
: default_val(new T(def_val))
{
}
This means that T must be copy constructible.
My understanding is also that I don't have to define a destructor at all, since the unique_ptr will automatically taking care of cleaning up itself?
Correct. That is 1 of 2 main purposes for unique_ptr, the 2nd being the guarantee that it has only one owner.
If you're using C++11 you could add also a constructor that accepts an rvalue ref
template<typename T>
class MyClass {
public:
MyClass(T&& def_val) : default_val(new T(std::move(def_val))) {}
MyClass::MyClass(const T& def_val) : default_val(new T(def_val)) {}
private:
std::unique_ptr<T> default_val;
};
now you accept both const ref, generating a copy, or temporaries

boost::variant and operator<< overloading

I wanted to test a simple thing like the following:
#include <iostream>
#include <boost/variant.hpp>
template<typename T1,typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1,T2>& dt){
os << dt.first << dt.second;
return os;
}
int main(){
boost::variant<int, std::pair<int,int>, bool> v;
v = std::pair<int,int>(3,3);
std::cout << v << std::endl;
}
This should actually work, because for normal types, like int, double and so on, it compiles.
boost::variant has a printer vistor which it uses internally to output the content to the stream.
Actually this fails to compile, but I do not really know the problem:
The codes fails here: in variant_io.hpp
template <typename OStream>
class printer
: public boost::static_visitor<>
{
private: // representation
OStream& out_;
public: // structors
explicit printer(OStream& out)
: out_( out )
{
}
public: // visitor interface
template <typename T>
void operator()(const T& operand) const
{
out_ << operand; // HEEEEEEERRRRREE!!!!!!!!!!!!
}
private:
printer& operator=(const printer&);
};
With the message:
/usr/local/include/boost/variant/detail/variant_io.hpp|64|error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&'
Does someone know what I did wrong, and why?
Thanks a lot!
Most likely it's not finding your overload of operator <<, and then gets confused trying to match some other overload, leading to whatever message you're getting.
What you did wrong: You overloaded the stream operator in the global namespace instead of the namespace the right-hand-side class is defined in, so it's not found by ADL.
Trying to overload the stream operator for a standard class is a doomed exercise in the first place, unfortunately. You can't actually do that. I'm not sure if there is an explicit rule against it. However, if you place the operator in namespace std as you have to in order to make it properly findable by ADL, you violate the rule that you can't add your own stuff to namespace std except in very specific cases, this not being one of them.
The bottom line is that std::pair doesn't have a stream operator, and it's not possible to legally add a generic one that is useful. You can add one for a specific instantiation, if one of the parameters is a class you defined yourself; in this case the operator needs to be placed next to your own class.
Overloaded operator<< must be findable by argument dependent lookup. That means you have to put it in associated namespace of one of the arguments.
The first argument has only one associated namespace, std. The second also has only one associated namespace, std. However it is only permitted to overload symbols in std for user-defined types. Since std::pair<int, int> is not user-defined type, this is not allowed. However it is allowed for a structure or class you define yourself. Obviously in that case it is easier to place the overload to your namespace, not std.
That said if you put that overload in namespace std, it will actually work.
Also note, that boost::tuple does have operator<< (in separate header that you have to include, but it does), so you can use that instead.

Resources