2010-06-16 49 views
81

Thật dễ dàng để tạo tên mới cho một loại, một biến hoặc một vùng tên. Nhưng làm thế nào để gán một tên mới cho một hàm? Ví dụ: tôi muốn sử dụng tên holler cho printf. #define là hiển nhiên ... bất kỳ cách nào khác?Làm thế nào để gán một bí danh cho một tên hàm trong C++?

Giải pháp:

  1. #define holler printf
  2. void (*p)() = fn; //function pointer
  3. void (&r)() = fn; //function reference
  4. inline void g(){ f(); }
+0

Nhờ tất cả các bạn. Các đồng nghiệp của tôi sẽ thích nó nhìn thấy 'void (& NewName) (some_vector &, float, float, float, float) = OldName;' trong lần kiểm tra tiếp theo của tôi. –

+14

không nhiều như họ sẽ thích nhìn thấy bạn sử dụng tên ngẫu nhiên cho tiêu chuẩn chức năng thư viện. – jalf

+2

Tôi không gây rối với 'printf' ở đây. Đó chỉ là một ví dụ. Vấn đề ở đây có nhiều hơn với những hạn chế của tiếng Anh hơn bất cứ điều gì khác. Tôi có một chức năng phục vụ mục đích A và mục đích B nhưng tôi đơn giản là không thể tìm thấy một tên duy nhất phục vụ cả hai mục đích ở đây. –

Trả lời

82

Có cách tiếp cận khác nhau:

  • Với C++ 11 với phi mẫu chức năng không quá tải bạn chỉ có thể sử dụng:

    const auto& new_fn_name = old_fn_name; 
    
  • Nếu chức năng này có nhiều quá tải, bạn nên sử dụng static_cast:

    const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name); 
    

    Ví dụ: có hai o verloads chức năng std::stoi

    int stoi (const string&, size_t*, int); 
    int stoi (const wstring&, size_t*, int); 
    

    Nếu bạn muốn thực hiện một bí danh cho phiên bản đầu tiên bạn nên sử dụng như sau:

    const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi); 
    

    Lưu ý: không có cách nào để làm cho một bí danh để chức năng quá tải sao cho tất cả các phiên bản quá tải của nó hoạt động, vì vậy bạn nên luôn xác định quá tải hàm chính xác nào bạn muốn.

  • Với C++ 14, bạn có thể tiến xa hơn với các biến mẫu constexpr. Cho phép bạn chức năng alias templated:

    template<typename T> 
    constexpr void old_function(/* args */); 
    
    template<typename T> 
    constexpr auto alias_to_old = old_function<T>; 
    
  • Hơn nữa, bắt đầu với C++ 11 bạn có một chức năng gọi là std::mem_fn cho phép chức năng thành viên bí danh.Xem ví dụ sau:

    struct A { 
        void f(int i) { 
         std::cout << "Argument: " << i << '\n'; 
        } 
    }; 
    
    
    A a; 
    
    auto greet = std::mem_fn(&A::f); // alias to member function 
    // prints "Argument: 5" 
    greet(a, 5); // you should provide an object each time you use this alias 
    
    // if you want to bind an object permanently use `std::bind` 
    greet_a = std::bind(greet, a, std::placeholders::_1); 
    greet_a(3); // equivalent to greet(a, 3) => a.f(3); 
    
+1

Tuyệt vời, làm thế nào về C++ 98? Tôi có một lớp w/2 "thiết lập lại" quá tải được sử dụng để thiết lập và thiết lập lại. Nội bộ, không sao cả. Đối với người dùng bên ngoài, tôi muốn bí danh là "set" để nó trực quan cho ngữ cảnh (thiết lập một đối tượng làm việc được thiết lập lại mặc định, rõ ràng() 'd etc .;). Các phương thức lớp: (1) "void (& set) (chuỗi const &, const bool, const bool);" (2) void (& set) (const chuỗi &, const int, const bool); 2 "thiết lập lại" w/chữ ký tương ứng làm công việc. Vì tôi có chữ ký trong khai báo lớp, tôi có thể chỉ khởi tạo lớp,: set (reset), set (reset). Nếu không, ví dụ tĩnh static_cast của bạn có hoạt động không? – Luv2code

+4

Dường như có vấn đề với cách tiếp cận biến mẫu 'constexpr': bí danh không thể thực hiện loại khấu trừ. Trình biên dịch yêu cầu tôi cung cấp danh sách tham số mẫu (Tôi đang viết một hàm mẫu có giá trị): không thể tham chiếu đến biến mẫu 'alias_to_old 'mà không có một danh sách đối số mẫu – user69818

+0

' constexpr auto new_fn_name = old_fn_name' hoạt động trong C++ 11 (ít nhất trong gcc 4.9.2) và tốt hơn là đặt '&'. Nó không yêu cầu phải luôn luôn được thực hiện thông qua con trỏ và do đó cho phép chức năng được inlined thay cho cuộc gọi. – ony

10

int (*holler)(const char*, ...) = std::printf;

21
typedef int (*printf_alias)(const char*, ...); 
printf_alias holler = std::printf; 

Bạn có nên làm tốt không.

+1

+1 cho "holler". – Mehrdad

+0

Không phải printf trong không gian tên chung? –

+3

toàn cầu nếu bạn bao gồm , nhưng trong tiêu chuẩn nếu bạn bao gồm Injektilo

31

Bạn có thể tạo một con trỏ hàm hay một tài liệu tham khảo chức năng:

void fn() 
{ 
} 

//... 

void (*p)() = fn;//function pointer 
void (&r)() = fn;//function reference 
+2

Cái này lấy cái bánh. Tôi không biết về các tham chiếu hàm. –

+0

@Vulcan: Chúng gần như giống nhau ở chỗ bạn có thể gọi cả hai trong số chúng với cùng cú pháp, nhưng địa chỉ của chúng khác nhau một chút. r không chiếm không gian bộ nhớ riêng của nó đang nắm giữ một địa chỉ. –

+1

Làm thế nào bạn sẽ gọi 'fn', sử dụng bí danh? Bạn có thể giải thích chức năng con trỏ và chức năng tham khảo? Họ khác nhau như thế nào? Họ có giống nhau không? – ma11hew28

7

Sử dụng một wrapper inline. Bạn nhận được cả hai API, nhưng duy trì việc triển khai đơn lẻ.

1

Từ fluentcpp: ALIAS_TEMPLATE_FUNCTION (f, g)

#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \ 
template<typename... Args> \ 
inline auto highLevelF(Args&&... args) -> decltype(lowLevelF(std::forward<Args>(args)...)) \ 
{ \ 
    return lowLevelF(std::forward<Args>(args)...); \ 
} 
Các vấn đề liên quan