2016-09-03 91 views
13

我還沒有使用C++ 11,所以我自己編寫了函數to_string(whatever)。只有在不存在的情況下才能編譯它們。如果我切換到C++ 11,應該跳過它們。我有這樣的事情:如果在C++之前沒有定義,定義函數/方法

#ifndef to_string 

string to_string(int a){ 
    string ret; 
    stringstream b; 
    b << a; 
    b >> ret; 
    return ret; 
} 

string to_string(double a){ 
    string ret; 
    stringstream b; 
    b << a; 
    b >> ret; 
    return ret; 
} 

#endif 

這顯然不起作用。是這樣的可能,如果是的話,怎麼樣?

+0

它可以預先C++ 11,見http://cpp.sh/86ldr –

+0

@ArnavBorborah好了,它不應該工作。 'std :: to_string'是C++ 11的東西 – xinaiz

+0

就我個人而言,我認爲這是一個非常糟糕的做法,對這個問題沒有很好的答案。 C++標準不提供'to_string',而是'std :: to_string',這是非常不同的。這意味着,如果你的標準不支持它,你不能使用'std :: to_string'。現在再想一想 - 假設您已經使用C++ 11。現在怎麼辦?如果你從接受的答案中使用宏,你會在你的餘生中使用它而不是'std :: to_string'嗎?非常非常糟糕的主意。 – xinaiz

回答

14

這是namespace存在的主要目的之一。

我的建議是包括在一個適當的命名空間中的個人作用,是這樣的:

namespace myns { 
    std::string to_string(...) { 
    // ... 
    } 
    // etc... 
} 

這是爲了避免未來衝突問題的根本。

之後,當您要使用該功能時,您可以使用MACRO替換簡單地選擇適當的功能。

喜歡的東西:

#if (__cplusplus >= 201103L) 
    #define my_tostring(X) std::to_string(X) 
#else 
    #define my_tostring(X) myns::to_string(X) 
#endif 

__cplusplus​​3210其中包含有關標準版本編譯的信息。


編輯:
東西少「暴力」,它會選擇按照標準版本,特定功能的正確的命名空間:

#if (__cplusplus >= 201103L) 
    using std::to_string; 
#else 
    using myns::to_string; 
#endif 

// ... somewhere 
to_string(/*...*/); // it should use the proper namespace 
+2

'#if(__cplusplus> = 201103L)'是我所需要的。謝啦。 – MaestroGlanz

+6

而不是#define一個宏,在'#ifdef'塊的每個分支中放置一個合適的'ns' :: to_string'。對編譯器名稱空間的暴力較少。 – Spencer

9

你不能測試它們是否會被定義爲這樣的,但你可以檢查語言版本:(有預定義的編譯器宏here的一個有用的集合)

#if __cplusplus < 201103L 

0

Boost.Config有一些macros來檢查是否支持/使用C++ 11功能。

+0

雖然我沒有在此列表中看到'to_string'函數的宏。 –

1

你可以把你的函數內宏,像這樣:

#ifndef to_string 
#define to_string 

//.... 

#endif 

然後,在另一個文件中,寫下這個:

#if __cplusplus >= 201103L 
    #undef to_string 
#else 
    #define to_string 
#endif 
+1

代碼不需要檢查是否定義了'to_string'; '#undef'可以用於尚未定義的名稱。 –

+0

感謝您解決這個問題,將解決這個問題 –

2

你可以玩SFINAE考慮到非模板重載優於模板重載。這將編譯在這兩個預C++ 11和C++ 11:

#include <sstream> 
#include <string> 
#include <iostream> 

using namespace std; 

namespace my { 
    template <bool V, class T> 
    struct enable_if { 
    }; 

    template <class T> 
    struct enable_if<true, T> { 
     typedef T type; 
    }; 

    template <class T1, class T2> 
    struct is_same { 
     static const bool value = false; 
    }; 

    template <class T> 
    struct is_same<T, T> { 
     static const bool value = true; 
    }; 
} 

template <class T> 
typename my::enable_if<my::is_same<T, int>::value 
         || my::is_same<T, double>::value, string>::type 
    to_string(T const& a) { 
    string ret; 
    stringstream b; 
    b << a; 
    b >> ret; 
    return ret; 
} 

int main() { 
    cout << to_string(2) << endl; 
    cout << to_string(3.4) << endl; 
}