2011-01-21 28 views
5

mã vấn đề của tôi:C++ quá tải: string literal vs tăng :: chức năng nhập nhằng

#include <string> 
#include <boost/function.hpp> 

void func (const std::string&) {} 
void func (const boost::function<void()>&) {} 

int main() { 
    func (main); // good 
    func ("bad"); 
    return 0; 
} 

=>

error: call of overloaded ‘func(const char [4])’ is ambiguous 
overload.cpp:4: note: candidates are: void func(const std::string&) 
overload.cpp:5: note:     void func(const boost::function<void()()>&) 

Tôi biết tôi có thể giải quyết điều này bằng cách gọi một cách rõ ràng func (string ("xấu ")); hoặc bằng cách cung cấp một func (const char *), nhưng tôi tự hỏi nếu có một cách để giữ bên người gọi như trong ví dụ và không giới thiệu quá tải.

Có thể có thứ gì đó có boost :: enable_if? Cảm ơn mọi gợi ý.

+0

bạn có thực sự nghĩ nguyên nhân là quá tải có chức năng 'boost ::' không, ví dụ bạn đã thử biên dịch mà không có quá tải? Công việc vừa ý? – Nim

+1

có nguyên nhân của nó bằng cách tăng :: chức năng. Ví dụ tôi đã đăng tái tạo toàn bộ tình huống. – denis

+0

vâng - đã không kiểm tra trước khi hỏi, chỉ hơi bemused rằng đây là trường hợp - có vẻ như nó là .. hmm .. ngắn cung cấp quá tải cho tất cả mọi thứ, không chắc chắn có một giải pháp gọn gàng cho việc này ... – Nim

Trả lời

4

Bạn không thể dễ dàng giải quyết việc này. boost::function<>std::function<> không chỉ hỗ trợ các functors có thể gọi là f(), mà còn trỏ tới các thành viên có thể gọi là (secondArg.*firstArg)() và các thành viên dữ liệu, vì vậy các nhà xây dựng của họ về cơ bản đã slurp mọi thứ và sau đó quyết định làm gì với loại. Nó không phải là tầm thường chút nào khi viết một lớp thử nghiệm SFINAE bảo vệ khỏi các chuyển đổi ngầm định (và tôi thậm chí không chắc chắn liệu nó có thể xảy ra hay không, vì Thư viện chuẩn không làm điều đó. một số lý do). Hãy nhớ rằng một kiểu có thể được gọi vì nhiều thuộc tính khác nhau - nó có thể có chức năng chuyển đổi để hoạt động kiểu con trỏ, vv .. Viết một lớp SFINAE có thể làm cho công việc này có nghĩa là từ chối chuyển đổi ẩn trong một số trường hợp và chấp nhận chuyển đổi ngầm các trường hợp khác dựa trên các thuộc tính thực sự không rõ ràng chút nào.

Nếu bạn muốn tránh sự mơ hồ này, tôi sẽ thử chỉ chọn một tên hàm khác hoặc nếu đó là vấn đề một lần, hãy thực hiện thao tác truyền ở phía người gọi.

+1

Câu hỏi cũ, nhưng đối với người đọc trong tương lai, có báo cáo lỗi về điều này cho 'std :: function'. Xem [2132. std :: function ambiguity] (http://cplusplus.github.io/LWG/lwg-active.html#2132) hiện đang được triển khai trong g ++ 4.8. –

0

ích này:

void func (const char *s) { func(string(s)); } 

cập nhật

template<class A0, ...> 
void func (const A0 &a0, ...) { 
    func(argize(a0), ...); // convert chars to strig, otherwise jut pass 
} 
+0

vấn đề là, mã sẽ được thực sự tự động tạo ra và có thể đã có rất nhiều tình trạng quá tải như func (string); func (chuỗi, int); func (string, int, boost :: function) và như vậy. Vì vậy, thêm char * -overloads là tiếc là không phải là một lựa chọn. – denis

+0

@denis xem cập nhật – Anycorn