2016-09-03 57 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; 
}