2016-09-03 34 views
13

Nie używam jeszcze C++ 11, więc sam napisałem funkcje to_string(whatever). Powinny być kompilowane tylko wtedy, gdy nie istnieją. Jeśli przejdę do C++ 11, powinny one zostać pominięte. Mam coś takiego:Zdefiniuj funkcję/metodę, jeśli nie została zdefiniowana przed 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 

To nie działa najwyraźniej. Czy jest coś takiego, a jeśli tak, to w jaki sposób?

+0

Działa pre-C++ 11, zobacz http://cpp.sh/86ldr –

+0

@ArnavBorborah dobrze, to nie powinno praca. 'std :: to_string' jest rzeczą C++ 11 – xinaiz

+0

Osobiście uważam, że jest to bardzo zła praktyka i nie ma dobrej odpowiedzi na to pytanie. Standard C++ nie poleca 'to_string', ale' std :: to_string', co jest bardzo różne. Oznacza to, że nie można użyć 'std :: to_string', jeśli twój standard go nie obsługuje. Teraz pomyśl jeszcze raz - załóżmy, że już używasz C++ 11. Co teraz?Jeśli używasz makra z zaakceptowanej odpowiedzi, czy przez resztę życia użyjesz go zamiast 'std :: to_string'? Bardzo, bardzo zły pomysł. – xinaiz

Odpowiedz

14

Jest to jeden z głównych celów istnienia namespace.

My sugerować jest to osobisty funkcji w odpowiedniej przestrzeni nazw, coś jak:

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

To jest fundamentalna w celu uniknięcia przyszłych problemów konfliktowych.

Następnie, gdy zamierzasz użyć tej funkcji, możesz łatwo wybrać odpowiednią funkcję z substytucją MACRO.

Coś jak:

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

Uwaga __cplusplus jest pre-defined macro kompilacją, która zawiera informacje o wersji standardowej.


Edit:
Coś mniej „brutalne”, to wybrać właściwą nazw dla tej konkretnej funkcji, zgodnie ze standardową wersją:

#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)' jest tym, czego potrzebowałem. Dzięki. – MaestroGlanz

+6

Zamiast #define makra, umieść odpowiednie 'using' ns' :: to_string' w każdej gałęzi bloku '# ifdef'. Mniej przemocy w przestrzeni nazw kompilatora. – Spencer

9

Nie można sprawdzić, czy są one zdefiniowane jako takie, ale można sprawdzić wersję językową: (. Jest użyteczny zbiór predefiniowanych makr kompilatora here)

#if __cplusplus < 201103L 

0

Boost.Config ma niektóre macros, aby sprawdzić, czy funkcje C++ 11 są obsługiwane/używane.

+0

Nie widzę jednak makra dla funkcji 'to_string' na tej liście. –

1

Można umieścić swoje funkcje Wewnątrz makro, takie jak to:

#ifndef to_string 
#define to_string 

//.... 

#endif 

Następnie w innym pliku wpisz:

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

Kod nie musi sprawdzać, czy zdefiniowano 'to_string'; '# undef' może być używany z nazwami, które nie zostały zdefiniowane. –

+0

Dzięki za wyczyszczenie tego, naprawię to –

2

Można grać z SFINAE, mając na uwadze, że nie-szablonowe przeciążenia są preferowane nad szablonowymi. To kompiluje zarówno pre-C++ 11 i 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; 
}