Dynamic pointer cast compile error when I compile with C++11 - c++11

I'm developping an app with OpenFrameworks with C++ language.
In my program there is a line that makes a dynamic cast pointer
Ref_<ImageUniform> p = o.cast<ImageUniform>();
Here is the class that implementing the cast() function implementation
template <typename T>
struct Ref_ : public ofPtr<T>
{
Ref_() {}
Ref_(T *t) : ofPtr<T>(t) {}
Ref_(const Ref_<T>& o) : ofPtr<T>(o) {}
Ref_(const ofPtr<T>& o) : ofPtr<T>(o) {}
template <typename TT>
Ref_<TT> cast() const { return dynamic_pointer_cast<TT>(*this); }
};
When I compile without the -std=c++11 it works.
But when I put the -std=c++11 it prints me a compile error and refers me to an internal file "ofTypes.h" of the library of OpenFrameworks at this line 191:
#else
template<typename Tp1>
ofPtr(const ofPtr<Tp1>& __r, std::__dynamic_cast_tag)
: std::shared_ptr<T>(__r, std::__dynamic_cast_tag()) { }
#endif
And also here is the compile error
......\libs\openFrameworks\types\ofTypes.h|193|error: no matching function >for call to 'std::shared_ptr::shared_ptr(const >ofPtr&, std::tr1::__dynamic_cast_tag)'|
#else
template
ofPtr(const ofPtr& __r, std::__dynamic_cast_tag)
: std::shared_ptr(__r, std::__dynamic_cast_tag()) { }
#endif

Either you should update your version of OpenFrameworks (which supports C++11), or you should not compile current code with C++11.
Now you have problem with below code
template<typename Tp1>
ofPtr(const ofPtr<Tp1>& __r, std::__dynamic_cast_tag)
: std::shared_ptr<T>(__r, std::__dynamic_cast_tag()) { }
when you compile this code without C++11, implementation of shared_ptr is taken from tr1/memory header. The code can be compiled because there is version of shared_ptr ctor which takes as second parameter __dynamic_cast_tag. When you try to compile the code with C++11, you will get error because shared_ptr implementation is taken from memory header (where there is no ctor of shared_ptr which takes __dynamic_cast_tag as second parameter).

Related

Is it possible to include code only inside one class?

I hope I can explain myself.
Supose I have next:
File "A.h":
#include "C.h"
public class A{
// Some code...
}
File "B.h":
#include "A.h"
public class B{
A a = new A(); //With this line I mean I'm using one instance of "A" inside "B.h"
//Some code...
}
Is it possible to include "C.h" ONLY inside "A.h"?
My problem is that the code I've included is giving me a lot of conflicts with usual functions. It's not an option to correct conflicts one by one, because there is a huge set of them. Also, my "C.h" code included is only a test code: after some tests, I will delete the include line.
Is there any way of 'bubbling' my include?
Thank you in advance.
EDIT: A.h and B.h are on the same namespace.
Is it possible to include "C.h" ONLY inside "A.h"?
No. Not to my knowledge.
If you have name conflicts, just include C.h within an other namespace, as #user202729 proposed. This can help.
But I guess you use C in A for tests and you cannot use it in C in A without the implementation which is not compatible to C++Cli or content from B.h.
We used the pimpl ideom (pointer to implementation).
Example:
c++/clr currently does not allow do be included directly and that's why sometimes you cannot use libraries you want to use (like C.h), because they do rely on the support of .
This is my C.h ( used by all the other headers)
struct LockImpl; // forward declaration of C.
class C
{
public:
C();
virtual ~C();
public:
void Lock() const;
void Unlock() const;
LockImpl* _Lock;
};
This is my C.cpp (compiled without /clr )
#include <mutex>
struct LockImpl
{
std::mutex mutex;
};
C::C() : _Lock(new LockImpl()) {}
C::~C() { delete _Lock; }
void C::Lock() const
{
_Lock->mutex.lock();
}
void C::Unlock() const
{
_Lock->mutex.unlock();
}
A.h
#include "C.h"
public class A{
C c;
void someMethod()
{
c.Lock() // I used another template for a RAII pattern class.
c.Unlock()
}
}

Template template for std::vector fails to build on icc16

I have a class that has a container in it. This container must be a template and must accept std::vector. The code needs to be C++11 standard. I have simplified for this question, but it is equivalent to:
#include <vector>
template <template <typename, typename...> class Container>
class Test {
Container<double> c;
};
class TestImplementation : public Test<std::vector> {};
Recently I have found this fails to build for icpc16 as shown by CompilerExplorer https://godbolt.org/g/AGgojV with the error message:
too few arguments for template template parameter "Container"
Container<double> c;
It compiles for gcc, clang and icpc17. Is this a bug in icpc16 or is my code incorrect?

ABI-compatible shared_ptr implementation

I am working on a COM-style complier cross-compatible plugin framework relying on compatible virtual table implementations for ABI compatibility.
I define interfaces containing only pure virtual member functions and an overridden delete operator to channel destruction to the place of implementation.
This works well with extern "C" factory functions instantiating the plugin implementation of the interface and returning an interface-type pointer.
However, I was wondering if smart pointers wouldn't be a more modern way to manage the lifetime of the plugin object. I think I have actually managed to
create a standard-layout shared_ptr/weak_ptr that uses a reference count object defined and implemented the same way as the plugin interfaces.
It looks something like this:
class IRefCount
{
public:
virtual void incRef() = 0;
virtual void decRef() = 0;
virtual bool incRefIfNZ() = 0;
virtual void incWRef() = 0;
virtual void decWRef() = 0;
virtual long uses() const = 0;
protected:
~ref_count_base() = default; //prohibit automatic storage
}
template <typename Ty>
class shared_ptr
{
private:
Ty* ptr_;
IRefCount* ref_count_;
public:
//member functions as defined by C++11 spec
}
Three questions:
Before the smart pointer the factory function looked like this:
extern "C" IPlugin* factory() { try { return new Plugin(); } catch (...) { return nullptr; } }
Now, it looks like this:
extern "C" shared_ptr<IPlugin> factory() { try { return shared_ptr<IPlugin>(new Plugin()); } catch (...) { return nullptr; } }
VS2013 is giving me warning C4190: 'factory' has C-linkage specified, but returns UDT 'shared_ptr' which is incompatible with C. According to MSDN this is OK, provided that both caller and callee are C++.
Are there any other potential issues with returning standard-layout objects from "C" linkage functions?
Calling conventions. Should I be specifying __stdcall for all pure-virtual interface functions and factory functions?
I am using <atomic> for the reference count. I am writing platform-independent code and I have not yet tried compiling for ARM. According to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html armcc does not implement std::atomic. Any better compilers/stl out there?

Initializing class with a lambda passed into constructor, C++11

Lets consider following example:
#include <functional>
#include <iostream>
using namespace std;
class Caller {
public:
Caller(function<void()> callback) {
callback();
}
};
main() {
#if defined(ONELINER)
Caller caller = [] { cout << "test"; };
#else
function<void()> fun = [] { cout << "test"; };
Caller caller(fun);
#endif // defined(ONELINER)
}
If we simply try to compile it (with -std=c++11 flag) it will happily finish, and display test when run. However if we define ONELINER macro compilation will fail with:
prog.cpp: In function 'int main()':
prog.cpp:17:40: error: conversion from 'main()::<lambda()>' to non-scalar type 'Caller' requested
Caller caller = [] { cout << "test"; };
I understand that this is caused by the fact that there is implicit conversion from lambda to std::function and then implicit conversion from std::function to Caller, and we cannot perform 2 conversions at the same time.
Is it somehow possible to make syntax Class object = lambda; work? I'm asking because I played recently with writing my own small testing framework for educational reasons and I thought that this:
UNIT_TEST(test_name) {
// test content
};
is much more elegant than
UNIT_TEST_BEGIN(test_name)
// unit test
UNIT_TEST_END()
The former can be achieved with lambdas passed into the UnitTest constructor. But with problem that I described I had to use dirty workaround like:
#define UNIT_TEST(test_name) \
::std::function<void(::Helper*)> test_name_helper; \
::UnitTest test_name ## _test = \
test_name_helper = \
[&] (::Helper* helper)
and it doesn't look elegant at all. But even if this can be done without lambdas I'm still intrigued whether Class object = lamda; syntax can be achieved.
Modify the constructor as such:
template<typename CB>
Caller(CB callback) {
callback();
}
That will allow it to accept any callable argument, be it a lambda, a std::function, function pointer or functor.
Unfortunately the constructor will also accept any other type as well, but give a compiler error when callback can't be "called" like a function.

Parameter pack expansion fails

Consider the following simplified C++ code:
template <typename ... TEventArgs>
struct Event
{
// ...
};
template <typename T>
struct Parameter
{
using Type = T;
// ...
};
template <typename ... Parameters>
struct Command
{
Event<typename Parameters::Type...> Invoked;
};
int main()
{
Command<Parameter<int>, Parameter<float>> c;
}
The Visual Studio C++ compiler (November 2013 CTP, Visual Studio 2013 Update 1) produces the following error:
source.cpp(17): error C3546: '...' : there are no parameter packs available to expand
Mingw 4.8.1. on the other hand compiles the code without any problems. Apparently, the Visual Studio compiler has a bug that prevents it from expanding the parameter pack when the expression involves accessing a type of the variadic parameters. Other expansions work, though. For instance, Event<std::vector<Parameters>...> Invoked; compiles successfully or you could even successfully access static members to call a variadic function like this in Command's constructor: SomeVariadicFunc(Parameters::SomeStaticFunc()...);.
So, the questions are:
1) Which compiler is wrong: Visual Studio or mingw? Although I don't see anything that would prevent the typename Parameters::Type parameter pack expansion from working, I'm not 100% sure it's valid C++.
2) Is there a work around? Basically, I would have to perform a projection from a "sequence" of Parameters to a "sequence" of Parameters::Type. Is that possible? I tried to construct that list using a recursive struct but I could only come up with something like myStruct<type1, mystruct<type2, mystruct<type3, ...>>>, which is not what I need.
Thank you for your help.
Yakk was able to come up with a workaround for the problem in the comments above. The final version that compiles perfectly with both Visual Studio an mingw is the following:
template <typename ... TEventArgs>
struct Event
{
// ...
};
template <typename T>
struct Parameter
{
using Type = T;
// ...
};
template <typename ... Parameters>
struct Command
{
private:
// Workaround for the Visual Studio bug
template<typename T> struct ExpandArgs
{
typedef typename T::Type Type;
};
public:
Event<typename ExpandArgs<Parameters>::Type...> Invoked;
};
int main()
{
Command<Parameter<int>, Parameter<float>> c;
}

Resources