简体   繁体   中英

Compatibility for C++11 code targetting Visual Studio 2008

I'm having an internal debate as to how I go about supporting a pre-C++11 compiler - Visual Studio 2008. This is required to build for Windows 2000 boxes (don't ask!).

I'm using a few C++11 features, such as std::to_string, std::mutex, and so forth. Currently, I've been able to get the low-level projects to compile by using boost and tr1 like:

#if _MSC_VER == 1500    
#   include <boost/thread/lock_guard.hpp>    
    using boost::lock_guard;
#   include <boost/thread/mutex.hpp>
    using boost::mutex;
#   include <memory>
    using std::tr1::shared_ptr;
#else
#   include <mutex>
    using std::lock_guard;
    using std::mutex;

#   include <memory>
    using std::shared_ptr;
    using std::unique_ptr;
#endif

and changing the source to shared_ptr func_name() instead of std::shared_ptr func_name() , for example. Far from perfect, and no doubt will have some subtle internal issues to fight with soon.

I'm now trying to figure out std::to_string , which cannot be adapted to the boost version so easily (there's also probably more issues in other classes I've not encountered yet).

As far as I can see, I have two-ish options:

1) Bite the bullet and preprocessor separate all backwards-compatibility code. This will uglify and bulk the code for something that isn't going to be used 99% of the time - but will be significantly quicker to implement.

2) Derive from std::string, and add the missing functionality as required. Repeat for other classes/functions. This will require 'using unknown classes' to people unfamiliar with the project, as well as additional time coding to fill in these gaps, with potential for bugs, but be the cleanest solution. It could also be used for future compatibility fixes too.

Swapping out every type isn't a big task, but I'd like to keep raw implementation types wherever possible, especially as the code needs to run on Linux and BSDs too. I'm not doing anything crazy that would be hard to backport either (no tuples, lambdas, or other things that'd be problematic in this context).

Has anyone had to do something similar before and found a nice solution?

As I do not have enough reputation to comment I will try to give an answer.

std::to_string is a free-standing function, so there is no need to derive. Depending on how important speed/formatting is for you could implement a my::to_string template function with boost::lexical_cast or std::stringstream. If speed really matters you should invest a bit more time and create manually overloads that use std::sprintf.

Here an example for the fist way:

#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>

namespace my {
    template<typename T> std::string to_string(T val){
        return boost::lexical_cast<std::string>(val);
    }
}

int main(){
    std::string foo = my::to_string(42.23);
    std::cout << foo << std::endl;
    return 0;
}

As general advice I would really try to hide os / compiler specific stuff in a few low level classes / files and use whatever you need there. But keep all the gory stuff out of your application code as good as you can.

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM