如果在C++中之前未定义函数/方法,那么需要定义它。

15

我还没有使用C++11,所以我自己编写了to_string(whatever)函数。如果它们不存在,它们应该被编译。如果我切换到C++11,它们应该被跳过。我的做法如下:

#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

这显然不起作用。类似这样的东西可行吗?如果是,怎么做?


它在C++11之前的版本中可用。请访问http://cpp.sh/86ldr。 - Arnav Borborah
@ArnavBorborah 嗯,这不应该起作用。std::to_string是C++11的东西。 - xinaiz
个人认为这是一种非常糟糕的实践,而且对于这个问题没有一个好的答案。C++标准不提供to_string,但是有std::to_string,它们之间有很大的区别。这意味着,如果您的标准不支持它,就不能使用std::to_string。现在再想想-假设您已经使用了C++11,那么现在怎么办?如果您使用接受的答案中的宏,您会终身使用它,而不是使用std::to_string吗?非常非常糟糕的想法。 - xinaiz
它无法工作的原因是#ifdef仅测试预处理器定义的存在,而不是像std::to_string这样的常规函数。这就是#ifdef可以测试的全部内容,因为预处理器指令由...预处理器执行。 - Marc van Leeuwen
5个回答

14

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

我的建议是将您的个人函数放在适当的名称空间中,例如:

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

这是非常基础的,以避免未来的冲突问题。

随后,当您使用该函数时,可以通过宏替换简单地选择适当的函数。

类似于:

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

注意 __cplusplus 是一个预定义宏,包含有关标准版本的编译信息。


编辑:
更温和的说法是,它将根据标准版本为该特定函数选择适当的命名空间:

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

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

3
“#if (__cplusplus >= 201103L)” 是我所需要的。谢谢。 - MaestroGlanz
6
与其使用 #define 宏定义,不如在每个 #ifdef 块的分支中放置一个适当的 using ns::to_string。这样可以减少对编译器名称空间的侵害。 - Spencer

9
你无法测试它们是否被定义为这样的,但是你可以检查语言版本:
#if __cplusplus < 201103L

(这里有一个有用的预定义编译器宏集合,可以在这里找到。)

2

您可以使用SFINAE技术,但需要注意非模板函数重载优先于模板函数。以下代码可在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;
}

1
您可以将函数放在宏中,像这样:

#ifndef to_string
#define to_string

//....

#endif

然后,在另一个文件中编写以下内容:
#if __cplusplus >= 201103L
    #undef to_string
#else
    #define to_string
#endif

1
代码不需要检查to_string是否被定义; #undef可以用于未定义的名称。 - Pete Becker

0

我在这个列表中没有看到to_string函数的宏。 - Baum mit Augen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接