c++11 forwarddeclare thread,mutex,chrono - c++11

I am aware that we should prefer to forward declare everything in header files, if possible but what about STL?
I have found that for iostream there is iosfwd.
What if i want to have a mutex declared in my class, like this:
class MyClass
{
.....
private:
std::mutex mMutex;
};
Should I include mutex header in my class header?
Or is there way to forwarddeclare it, like:
class std::mutex;
class MyClass{...};
Same goes for chrono, and thread as well.
Any thoughts on that is appreacited. Thanks!

There is no portable way to forward declare std::objects, except as specified (e.g. <iosfwd>). And there are no forwarding headers for mutex, thread or chrono.

The C++ 11 standard states that forward declaring classes that are part of the std namespace cannot be forward declared (section 17.6.4.2.1):
The behavior of a C++ program is undefined if it adds declarations or
definitions to namespace std or to a namespace within namespace std
unless otherwise specified.
However for some reason the following piece of code does compile and run.
.h:
#pragma once
// Forward declaration of thread class that is part of the std namespace
namespace std
{
class thread;
}
// Example declaration of a class using the forward declared class
class ExampleClass
{
private:
std::thread * _thread;
void ThreadFunction(){}
}
.cpp
#include "ExampleClass.h"
#include <thread>
ExampleClass::ExampleClass() :
_thread(new std::thread(std::bind(&ExampleClass::ThreadFunction, this)))
{
}
I compiled the code using visual studio 2015, perhaps that the C++ 11 standard statement no longer applies to C++14/17/20?

Related

Macro Missing Type Specifier with Static Variadic

I am attempting to automatically register data types against a factory. The first non-generalized version worked, but cannot define the registration macro since the factory was changed to a variadic. The compile error is...
error C4430 missing type specifier - int assumed. Not: C++ does
not support default-int.
#define GH_FACTORY_GET_LICENSE_FACTORY \
Factory<ILicenseManager, bool>::getFactory();
#define GH_FACTORY_REGISTER_LICENSE_MANAGER( ) \
Factory<ILicenseManager, bool>::getFactory().registerType();
Example 1
class A
{
public:
A()
{
Factory<gh::license::ILicenseManager, bool>::getFactory().registerType();
}
~A() {}
};
static class A foo;
Example 2
GH_FACTORY_REGISTER_LICENSE_MANAGER;
When using
GH_FACTORY_GET_LICENSE_FACTORY
and
GH_FACTORY_REGISTER_LICENSE_MANAGER
in local scope it builds, but when using
GH_FACTORY_REGISTER_LICENSE_MANAGER
in global scope it doesn't build (looks like the class is undefined?). Any ideas? Would love to understand why this happens.

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.

Getting c++11 auto initialization syntax right

I am newbie programmer in C++ (but a veteran programmer in other languages) and I am trying to use "Modern C++" in my code.
I am wondering what I am doing wrong here, trying to initialize an istream from a boost::asio::streambuf:
#include <iostream>
#include <boost/asio/streambuf.hpp>
class A {
public:
void foo();
private:
boost::asio::streambuf cmdStreamBuf_{};
};
void A::foo() {
std::istream is1{&cmdStreamBuf_}; // works
auto is2 = std::istream{&cmdStreamBuf_}; // does not compile
}
I get this error:
try.cpp:13:41: error: use of deleted function 'std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)'
I am not trying to copy; I thought I was constructing an std::istream!
Since all the answers were in the comments, I thought I'd finish this off by doing an official answer myself.
I am using a c++ library that doesn't have movable streams, and this matters because
auto is2 = std::istream{&cmdStreamBuf_};
creates a new std::istream and then initializes is2 with that rvalue (temporary object). It initializes it by calling the copy constructor or the move constructor. My c++ library apparently does not have either of these constructors, therefore the call fails.
I had originally thought that
auto varname = typename{...};
was the conceptually the same as
typename varname{...};
but it is not. So, this is an instance where you can't use auto to create a variable.
(sigh) And I was really hyped on using auto everywhere.

What do I need to do to have both C++/CLI and unmanaged C++11 enum classes?

The new enum class type in C++11 came from the C++/CLI version with the same name but they are quite different and are causing me problems.
I have a library written in C++11 containing several structures like (really simplified here):
// File.h
enum class MyEnum : unsigned int
{
Val1,
Val2
};
struct MyStruct
{
MyEnum value;
MyStruct(MyEnum v) : value(v) {}
};
I am trying to reach this code from a C++/CLI class library to expose it to .NET. I include the file like this:
#pragma unmanaged
#include "File.h"
#pragma managed
The problem is that the enum constructor yields a compile error message like:
error C3821: 'v': managed type or function cannot be used in an unmanaged function
suggesting that the compiler still interprets the enum class as a C++/CLI enum class even though I am within the unmanaged section and it really should interpret it as a C++11 enum class. Is there anything I can do about this?
EDIT: I am using VS2012. Please let me know if VS2013 fixes this.
I have the same problem in VS2013. In my case, I'm including an unmanaged enum class but the compiler is generating errors because it thinks it's a managed enum class. With the help from the comments on the question, I was able to fix it by removing all forward declarations of the enum. It looks like this is a compiler bug, where the forward declaration ignores the #pragma unmanaged directive.
I've created an example of how to reproduce the bug here:
#pragma managed(push, off)
enum class TestEnum
{
One,
Two,
Three,
};
#include <vector>
enum class TestEnum; // Forward declaration after actual declaration causes the bug
#pragma managed(pop)
int main(array<System::String ^> ^args)
{
// error C3699: '&&' : cannot use this indirection on type 'TestEnum'
std::vector<TestEnum> enums;
return 0;
}
I've reported the issue to Microsoft here:
https://connect.microsoft.com/VisualStudio/feedback/details/1218131

Resources