Подтвердить что ты не робот

Определить функцию/метод, если он не определен до С++

Я еще не использую С++ 11, поэтому я сам написал функции to_string(whatever). Их следует компилировать только в том случае, если они не существуют. Если я переключусь на С++ 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

Это не работает. Что-то вроде этого возможно, и если да, то как?

4b9b3361

Ответ 1

Это одна из основных целей 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 представляет собой предопределенный макрос, который содержит компиляцию информации о стандартной версии.


Edit:
Что-то менее "жестокое", оно выберет подходящее пространство имен для этой конкретной функции в соответствии со стандартной версией:

#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

(Там есть полезная коллекция предопределенных макросов компилятора здесь.)

Ответ 3

Вы можете играть с SFINAE, имея в виду, что перетаскивание без шаблонов предпочтительнее шаблонных. Это компилируется как в pre-С++ 11, так и в С++ 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;
}

Ответ 4

Вы можете поместить свои функции внутри макроса, например:

#ifndef to_string
#define to_string

//....

#endif

Затем в другом файле напишите:

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

Ответ 5

Boost.Config имеет macros, чтобы проверьте, поддерживаются/используются функции С++ 11.