2012-10-12 32 views
8

của một chức năng liên kết ngôn ngữ là một phần của loại của nó:Có thể chuyên mẫu về liên kết ngôn ngữ không?

7.5.1 [dcl.link] của ISO C++ tiêu chuẩn:

Các liên kết ngôn ngữ mặc định của tất cả các loại chức năng, tên hàm, và biến tên là liên kết ngôn ngữ C++. Hai loại hàm với các liên kết ngôn ngữ khác nhau là các loại riêng biệt ngay cả khi chúng giống nhau.

Có thể chuyên mẫu trên loại liên kết của con trỏ hàm hay nhìn vào kiểu con trỏ hàm để xác định liên kết của nó tại thời gian biên dịch không?

nỗ lực đầu tiên này dường như không hợp pháp:

#include <iostream> 
#include <typeinfo> 

struct cpp {}; 
struct c {}; 

extern "C++" void foo() 
{ 
    std::cout << "foo" << std::endl; 
} 

extern "C" void bar() 
{ 
    std::cout << "bar" << std::endl; 
} 

template<typename> struct linkage; 

template<> 
    struct linkage<void(*)()> 
{ 
    typedef cpp type; 
}; 

template<> 
    struct linkage<extern "C" void(*)()> 
{ 
    typedef c type; 
} 


int main() 
{ 
    std::cout << "linkage of foo: " << typeid(linkage<decltype(&foo)>::type).name() << std::endl; 
    std::cout << "linkage of bar: " << typeid(linkage<decltype(&bar)>::type).name() << std::endl; 
    return 0; 
} 

g++-4.6 kết quả đầu ra:

$ g++ -std=c++0x test.cpp 
test.cpp:26:38: error: template argument 1 is invalid 
test.cpp:26:3: error: new types may not be defined in a return type 
test.cpp:26:3: note: (perhaps a semicolon is missing after the definition of ‘<type error>’) 
test.cpp:32:10: error: two or more data types in declaration of ‘main’ 

Có một số ứng dụng của SFINAE rằng có thể thực hiện chức năng này?

Trả lời

7

Có, tôi tin rằng bạn sẽ có thể chuyên về một mẫu dựa trên liên kết ngôn ngữ của nó theo tiêu chuẩn C++. Tôi đã thử nghiệm đoạn mã sau với Comeau compiler online và nó được biên dịch không có lỗi:

#include <iostream> 
#include <typeinfo> 

struct cpp {}; 
struct c {}; 

extern "C++" typedef void(*cppfunc)(); 
extern "C" typedef void(*cfunc)(); 

extern "C++" void foo() 
{ 
    std::cout << "foo" << std::endl; 
} 

extern "C" void bar() 
{ 
    std::cout << "bar" << std::endl; 
} 

template<typename> struct linkage; 

template<> 
    struct linkage<cppfunc> 
{ 
    typedef cpp type; 
}; 

template<> 
    struct linkage<cfunc> 
{ 
    typedef c type; 
}; 


int main() 
{ 
    std::cout << "linkage of foo: " << typeid(linkage<decltype(&foo)>::type).name() << std::endl; 
    std::cout << "linkage of bar: " << typeid(linkage<decltype(&bar)>::type).name() << std::endl; 
    return 0; 
} 

Tuy nhiên, tôi tin rằng due to a gcc bug, gcc không phân biệt các loại chức năng dựa trên mối liên hệ ngôn ngữ, vì vậy đây là không thể với gcc (và nó dường như không chắc chắn khi nào họ sẽ sửa lỗi này).

+1

Bạn có lẽ có một trích dẫn cụ thể cho biết rằng liên kết là một phần của thông tin loại mà các mẫu C++ dựa trên? –

+4

@NicolBolas: Không, tôi thì không. Tuy nhiên, tôi nghĩ rằng câu hỏi trong câu hỏi là rõ ràng: 'Hai loại chức năng với các liên kết ngôn ngữ khác nhau là các loại riêng biệt'. Và từ [14.4 Kiểu tương đương]: 'Hai mẫu-id tham chiếu cùng một lớp hoặc hàm nếu kiểu mẫu-đối số tương ứng của chúng là cùng loại'. –

+1

@NicolBolas: 7,5.1 được trích dẫn trong câu hỏi ... –

Các vấn đề liên quan