2016-09-03 18 views
13

Tôi chưa sử dụng C++ 11, vì vậy tôi đã tự viết các hàm to_string(whatever). Chúng chỉ nên được biên dịch nếu chúng không tồn tại. Nếu tôi chuyển sang C++ 11, chúng sẽ bị bỏ qua. Tôi có một cái gì đó như thế này:Xác định hàm/phương thức nếu không được xác định trước 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 

Điều này không hoạt động rõ ràng. Là một cái gì đó như thế này có thể và nếu có, làm thế nào?

+0

Nó hoạt động pre-C++ 11, Xem http://cpp.sh/86ldr –

+0

@ArnavBorborah Vâng, nó không nên công việc. 'std :: to_string' là C++ 11 điều – xinaiz

+0

Cá nhân tôi nghĩ rằng đó là một thực hành rất xấu, và không có câu trả lời tốt cho câu hỏi này. C + + tiêu chuẩn không chứng minh 'to_string', nhưng' std :: to_string', mà là rất khác nhau. Điều đó có nghĩa là bạn không thể sử dụng 'std :: to_string' nếu tiêu chuẩn của bạn không hỗ trợ nó. Bây giờ hãy nghĩ lại - giả sử rằng bạn đã sử dụng C++ 11. Gì bây giờ?Nếu bạn sử dụng macro từ câu trả lời được chấp nhận, bạn sẽ cho phần còn lại của cuộc sống của bạn sử dụng nó thay vì 'std :: to_string'? Ý tưởng rất, rất tệ. – xinaiz

Trả lời

14

Đây là một trong những mục đích chính của namespace sự tồn tại.

tôi đề nghị là bao gồm chức năng cá nhân của bạn trong một không gian tên thích hợp, một cái gì đó như:

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

Đây là nền tảng để tránh các vấn đề xung đột trong tương lai.

Sau đó, khi bạn định sử dụng chức năng đó, bạn có thể đơn giản chọn chức năng phù hợp với thay thế MACRO.

Cái gì như:

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

Note __cplusplus là một pre-defined macro chứa biên dịch thông tin về phiên bản tiêu chuẩn.


Edit:
Something ít "hung hăng", nó sẽ chọn không gian tên thích hợp cho rằng chức năng cụ thể phù hợp với phiên bản tiêu chuẩn:

#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)' là những gì tôi cần. Cảm ơn người đàn ông. – MaestroGlanz

+6

Thay vì # define một macro, đặt một 'thích' ns' :: to_string' vào mỗi nhánh của khối '# ifdef'. Ít bạo lực hơn cho không gian tên trình biên dịch của bạn. – Spencer

9

Bạn không thể kiểm tra xem chúng được xác định như vậy, nhưng bạn có thể kiểm tra phiên bản ngôn ngữ: (. Có một bộ sưu tập hữu ích của macro biên dịch được xác định trước here)

#if __cplusplus < 201103L 

0

Boost.Config có một số macros để kiểm tra xem các tính năng của C++ 11 có được hỗ trợ/sử dụng hay không.

+0

Tôi không thấy macro cho hàm 'to_string' trong danh sách này. –

1

Bạn có thể đặt các chức năng của mình bên trong một macro, như sau:

#ifndef to_string 
#define to_string 

//.... 

#endif 

Sau đó, trong tệp khác, hãy viết:

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

Mã không cần kiểm tra xem 'to_string' được định nghĩa hay chưa; '# undef' có thể được sử dụng với các tên chưa được xác định. –

+0

Cảm ơn bạn đã xóa nội dung đó, sẽ khắc phục điều đó –

2

Bạn có thể chơi với SFINAE lưu ý rằng quá tải không phải mẫu được ưu tiên hơn so với mẫu. Đây biên dịch trong cả hai pre-C++ 11 và 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; 
} 
Các vấn đề liên quan