boost::shared_ptr vs std::tr1::shared_ptr on multi os compilation - c++

I have maintained different code for browser plugin(c++) for windows and mac system. The difference of the code is only for shared pointer.
In windows version I am using std::tr1::shared_ptr and on Mac version am using boost::shared_ptr.
Now I wanted to merge these code into one.I wanted to use std::tr1::shared_ptr in both code and maintain single source code but two different solution/project folder.
This browser plugin support up to OSX 10.5 onwards.Presently I am compiling in Xcode 4.6.2(Apple LLVM compiler).Basically I am Windows programmer and mostly work on Visual Studio.
My question is Will Mac Older version will support plugin with this change.Is this is a good idea ?
Please let me know whether boost is useful in this case.

First of all, boost::shared_ptr and std::tr1::shared_ptr are almost the same, but if you can you should use std::shared_ptr instead by enabling C++11 support (default on VS12 I think, to be enabled in clang / llvm).
The shared_ptr is a template class wrapping a pointer, thus the whole code is instanciated when you compile your program: the original class implementation resides in a header file which is incorporated in your translation unit (each separate file being built).
As such, you don't need any specific library to use shared_ptr (neither a .dll nor a .so or something else on Mac). So your program will run on any machine for which it has been built, you don't require additional library to run it.
You can also - for compatibility reason - use your own wrapper around the shared_ptr:
namespace my_code {
#if defined(_STD_TR1_SHARED_PTR)
using std::tr1::shared_ptr;
#elif defined(_STD_SHARED_PTR)
using std::shared_ptr;
#else
using boost::shared_ptr;
#endif
}
Thus you can access my_code::shared_ptr which will resolve to the appropriate type depending on the macros you define. Note that this only works if you use a compatible interface for all those types, but this should be the case.

Why don't you just test it? An easy first step would be to use a typedef to change the actual shared pointer definition under the hood:
namespace myNs{
#ifdef _USE_STD_SRDPTR
typedef std::shared_ptr sharedPtr;
#else
typedef boost::shared_ptr sharedPtr; //default to boost if no symbol defined
#endif
}
//in code replace old shared pointer usage
myNs::sharedPtr<Fruit> ourFruit( new Banana(WONKY) );
This way you can replace it in both code libraries, and change the underlying implementation whenever you want. You can add support for more options (e.g. the tr1 version) as you need to without changing your code. Of course all options need to have the same interface or the code won't compile.

Related

How to make sure code (c++) written in Xcode can compile on other platforms?

I am a beginner was trying to do some C++ programming on Xcode. It works fine, but when I try to compile the same c++ file on my windows pc using VS, there were some errors. After I look at my code closely, there are really some stupid mistakes that I have made which caused the errors, but Xcode seemed to have ignored them...
My question is that is there any setting that I need to change to prevent Xcode from being so smart?
For example, the following code can actually compile in xcode:
#include <iostream>
using namespace std;
int main() {
if (true or false){
cout << "How is this possible? \n";
}
return 0;
}
There are also other cases where the code is actually wrong, but it can compile just fine is Xcode which is the annoying part and I want to disable that.
As far as I can see there is nothing wrong with your code.
The ISO C++ standard does not specify which standard headers are included by other standard headers. So, it is entirely possible that the version of iostream used by Xcode directly or indirectly includes ciso646. Whereas Visual Studio's version of iostream does not include ciso646. There are many similar cases with other headers. You just need to read the error messages and realize that your error (when you move your file to a different platform) is due to a missing header file.
It would be nice if writing portable code meant writing code in accordance with the C++ standard specification, but unfortunately that's not the case. Although there are various compiler options on various implementations which can help bring different implementations closer together, in general you will just have to bring the code into the target environment and actually test it there.
So ultimately writing portable code means you'll have to learn some subset of C++ that is accepted by all the implementations you want to target.
or is an 'alternative token' in C++, and VS is incorrect to reject it. There's no option in Xcode to disable support for alternative tokens. However VS has non-standard support for or as a macro using the header <ciso646>, and Xcode does have a header <ciso646> which does nothing (as the standard specifies). So you can write code which uses or and which works in both Xcode and VS by including this header.
#include <iostream>
#include <ciso646> // does nothing in Xcode, allows `or` in VS
using namespace std;
int main() {
if (true or false){
cout << "How is this possible? \n";
}
return 0;
}
Unfortunately VS can't support all of the alternative tokens through macros and so Xcode will still support some that VS doesn't.
There are also other cases where the code is actually wrong, but it can compile just fine is Xcode which is the annoying part and I want to disable that.
If you give specific examples then I can provide additional advice on how to write portable code.
Rather than changing your Xcode settings, I suggest cross-checking your code using another development environment.
If you're looking for something cheap and full-proof. Download a VirtualBox Windows VM, and run download Dev C++ (bloodhshed)
VS does not support or: you need to use || instead.
You can include some special files but it doesn't inject or sufficiently well into the language for it to work in all instances.
If you want to suppress use of or (and your compiler supports no better way)
#define it to something that emits a compiler error, for example
#define or OR
This at least means that the nature of the compilation errors will be identical on Xcode and VC.

Create automatic C wrapper for C++ library?

Let say I have a C++ DLL. AFAIK, there is no widely-adopted ABI standard for C++, therefore to make sure it works and does not depend on the compiler of the target application I would need to wrap my library in a C interface.
Are there any tools that can automatically generate such interface? Would also be nice if they could generate wrappers around C interface to look as if they are original C++ objects, e.g.
Foo* f = new Foo(); // FooWrapper* fw = Foo_create();
f->bar("test"); // Foo_bar(fw, "test")
translates into C functions that are invoked in my library using generated C ABI. I understand that C++ is fairly complicated language and not everything can be easily wrapped in a C interface, but I was wondering if there are any such solutions that even support a subset of the C++ language (maybe with the help of some manually written IDL/XML files)?
there is no widely-adopted ABI standard for C++
I'm pretty sure that is a bit exaggerated - there aren't THAT many different compilers available for any given platform, so it would probably be easier to just produce a DLL for each vendor (e.g. Microsoft, GCC on Windows, GCC on Linux, Sun and GCC for Solaris, GCC for MacOS - CLANG is compatible with GCC as far as I know).
To add a C layer interface basically means that the interface layer must not:
1. Use any objects of that require special copy/assignment/construction behaviour.
2. Use any "throw" exceptions.
3. Use virtual functions.
across that interface.
It is my opinion that it's easier to "fix" the problems caused by "lack of ABI" than it is to make a good interface suitable for C++ use with a C interface in the middle of it.
If you want a way to make C++ code callable from other compilers/standard libraries, you can use cppcomponents from https://github.com/jbandela/cppcomponents. Full disclosure - I am the author of the library.
Here is a simple hello world example
First make a file called library.h
In this file you will define the Component
#include <cppcomponents/cppcomponents.hpp>
struct IPerson
:public cppcomponents::define_interface<cppcomponents::uuid<0xc618fd04,0xaa62,0x46e0,0xaeb8,0x6605eb4a1e64>>
{
std::string SayHello();
CPPCOMPONENTS_CONSTRUCT(IPerson,SayHello);
};
inline std::string PersonId(){return "library!Person";}
typedef cppcomponents::runtime_class<PersonId,cppcomponents::object_interfaces<IPerson>> Person_t;
typedef cppcomponents::use_runtime_class<Person_t> Person;
Next create library.cpp
In this file you will implement the interface and component
#include "library.h"
struct PersonImplementation:cppcomponents::implement_runtime_class<PersonImplementation,Person_t>
{
std::string SayHello(){return "Hello World\n";}
};
CPPCOMPONENTS_DEFINE_FACTORY(PersonImplementation);
Finally here is you main program (call it example1.cpp) that uses your implementation
#include "library.h"
#include <iostream>
int main(){
Person p;
std::cout << p.SayHello();
}
To build the program you will need to download cppcomponents (just clone from the git link above). It is a header only library and needs only a c++11 compiler.
Here is how you would build it on Windows
cl /EHsc example1.cpp /I pathtocppcomponents
g++ -std=c++11 library.cpp -o library.dll -shared -I pathtocppcomponents
where pathocppcomponents is the directory of cppcomponents.
I am assuming you have cl and g++ in your path.
To run the program, make sure library.dll is in the same directory as example1.exe and run example1.exe
This library requires fairly compliant c++11 support, so it needs MSVC 2013 Preview, and at least g++ 4.7. This library works on both Windows and Linux.
As far as I know the answer is no and you are supposed to handle this by yourself with a little bit of "hacking" and modifications, for example your t variable which is an std::string can possibly be "externed" to a C interface by t.c_str() because c_str returns a const char * which is a type that C understands without any problem at all.
I personally don't find C++ complicated, I can't see that "ABI issue" either, I mean nothing is perfect but you are externalizing to C your entire code base to "solve" this issue ? Just use C in the first place, also C it's no easy language to deal with either, for example in C there is not even the notion of "string", and problems that are trivial to solve in C++ while keeping everything type-safe, are really challenging in C if you want to meet the same goal.
I think that you are going a little bit too far with this, and you are complicating things, as it is now you have 3 + 1 main options on the most popular platforms :
libsupc++
libcxxrt
libc++abi
plus the whetever ABI is for the MSVC of your choice ( aka "only god knows")
for me, on linux, libsupc++ works very well, I'm following the libc++abi project and I don't see any big problem either, the only real problem with this is that llvm is basically an Apple oriented project for now, so there isn't that real and good support for the other platforms, but libc++abi compiles and works quite well on linux too ( although it's basically useless and pointless, on linux there is libsupc++ already.) .
I also would never ever use MSVC under Windows, in my opinion it's better to stick with a GCC-like compiler such as mingw, you got bleeding edge features, and you can simplify your codebase and your building phase a lot.

BOOST_MESSAGE undefined

I have installed boost_1_54 on windows by checkout from svn and then
bootstrap
.\b2
QuantLib library dependent on boost compiles well all but one project: test-suite which uses BOOST_MESSAGE. this is undefined. I can see that there is no BOOST_MESSAGE in my version of boost.
Therefore is this QuantLib incompatibility or have I missed something?
On my linux boost version the same thing applies to BOOST_MESSAGE - it is undefined
I have seen this but I am not sure how to interpret this.
I'm afraid you gave us more credit than we deserved :)
We haven't compiled QuantLib against Boost svn yet. The latest I've tried is Boost 1.53 (the latest released version) in which BOOST_MESSAGE was still available.
Thanks for the heads-up, though. I'll patch the library so that it's ready for next version. As mentioned in the comments, it should be as simple as adding
#if BOOST_VERSION > 105300
#define BOOST_MESSAGE(msg) BOOST_TEST_MESSAGE(msg)
#endif
to test-suite/utilities.hpp.
on linux I had to add
libboost_unit_test_framework.so
to the Linker->Libraries and
#include <boost/test/unit_test.hpp>
#define BOOST_MESSAGE( M ) BOOST_TEST_MESSAGE( M )
is already present in test/test_tools.hpp.
on windows I have different #defines and this is not present, so I added it to the
unit_test_log.hpp
where BOOST_TEST_MESSAGE is defined (in boost files to avoid same issue again in the case of other applications using BOOST_MESSAGE).
BOOST_MESSAGE issue resolved but still can't disambiguate
const void* = boost::test_tools::check_is_close
and
const void* = boost::test_tools::check_is_small
because these are templates. so the solution is to remove it (test-suite compiles well) or use appropriate pointers to function templates
on Windows, after romoval or function
_use_check
in utilities.hpp
changed to not have pointers to TEMPLATE functions as default, so changed to:
void _use_check(
const void*,
const void*) const {}
there were still errors while building test-suite project. unresolved externals: fdmhestonfwdop, fdmblackscholesfwdop, fdmsquarerootfwdop. obviously this classes (headers+source) I had to add to Quantlib project, build library QuantLib-vc110-mt-gd.lib again and rebuild test-suite project then.
after pleasure with VS linker error "lnk1210 exceeded internal ilk size limit link with incremental no" (it really likes RAM, but on windows I have this resource quite limited), it is OK. compiled. : p

How to get headers for unordered_set in gcc v4.1.2?

I'd like to use unordered_set without installing Boost. I tried to add --std=gnu++0x but it is not a recognized option. Does v4.1.2 include unordered_set? If so, how do I get the header file for it?
This is a Centos 4 machine.
unordered_set is in the purview of the standard C++ library, not gcc, the compiler (although most programs built using gcc are linked against libstdc++).
The way you generally include it is #include <tr1/unordered_set>. Then, to use it, you must either do a using std::tr1::unordered_set; or qualify the name each time.
The C++ standard version you choose to use doesn't have much effect because that's the language standard, and the availability of standard library constructs is semi-independent.
IIRC, gcc-4.2 did not have unordered containers at least not in namespace std. I know -std=c++0x was not in place till around gcc-4.3.
Have you tried this:
#include <tr1/unordered_set>
...
std::tr1::unordered_set<int> usint;
...
Notice the tr1/ in the header.
Having said that, gcc-4.1 is pretty old. Any chance you could try say gcc-4.5 or 4.6 and use the std container?

How to use the boost library (including shared_ptr) with the Android NDK and STLport

This is more of an answer than a question, because I've figured it out, at least as far as cleanly compiling the library. The main issue for me was to get shared_ptr working.
Ingredients:
Boost v. 1.45.0
The version of STLport at http://www.anddev.org/viewtopic.php?p=29939.
Version r4b of the NDK.
Directions:
In your Android.mk file add:
LOCAL_CFLAGS += -DBOOST_EXCEPTION_DISABLE -D_STLP_NO_EXCEPTIONS -DOS_ANDROID -D_STLP_USE_SIMPLE_NODE_ALLOC
Remove the call to __stl_throw_length_error at line 613 of stlport/stl/_string.h. You can use _STLP_NO_EXCEPTIONS if you like.
Edit boost/boost/smart_ptr/shared_ptr.hpp after line 261 to get rid of the call to boost::throw_exception in the shared_ptr constructor. I used #ifndef BOOST_EXCEPTION_DISABLE around the entire body of the method. (But see the answer below.)
Next you need to supply some missing pieces. Create a header file with the following:
#ifdef OS_ANDROID
#include <exception>
namespace std
{
struct bad_alloc : public exception { bad_alloc operator()(){}};
}
#endif
and a source file with a stripped-down exception class to support bad_alloc:
#ifdef OS_ANDROID
#include <exception>
namespace std
{
exception::exception() {}
exception::~exception() {}
const char* exception::what() const {}
}
#endif
Include the header wherever you're including boost/shared_ptr.hpp. Compile the source and add it to your library.
It turned out that this approach does not entirely work when compiling a debuggable library. The release library is compiled with -O2 which optimizes out some infelicities, but the debug library is done with -O0 which reveals some additional problems. Furthermore, I wasn't too happy about having to edit the boost files. So with some additional study, I've come up with the following solution.
First, don't edit any of the boost files. Instead add the following to the header within the std namespace:
struct bad_cast : public exception {bad_cast operator()(){}};
Next add the following to the source file:
namespace boost
{
void throw_exception(std::exception const&) {}
}
This now compiles and links into the application even with android:debuggable="true" in AndroidManifest.xml. It doesn't run in the emulator, but then it wasn't doing that before I included this library either.
Notably, NDK r5 comes with STLport, and the GNU STL, and so the hacks here are no longer going to be necessary now that there is a) STL support b) exception support in the NDK C++ compiler.
Another workaround for shared_ptr in particular is to use boost::intrusive_ptr instead. This is not always possible, but worked for my situation.
The current version of Android NDK (r9) now supports exceptions.
The capabilities of the various runtimes vary. See this table:
C++ C++ Standard
Exceptions RTTI Library
system no no no
gabi++ yes yes no
stlport yes yes yes
gnustl yes yes yes
stlport can get used in non-GPL binarys. It's still flagged as experimantal, but you can use it with clang and gcc.
See http://developer.android.com/tools/sdk/ndk/