2013-06-14 12 views
8

Có một kỹ thuật đôi khi tôi sử dụng khi trọng template chức năng mà đi như thế này:Rỗng eni gói enums - họ làm cho hai chức năng khác nhau?

#include <utility> 
template<int> struct unique_enum { enum class type {}; }; 
template<int index> using UniqueEnum = typename unique_enum<index>::type; 
template<bool b, int index=1> 
using EnableFuncIf = typename std::enable_if< b, UniqueEnum<index> >::type; 
template<bool b, int index=1> 
using DisableFuncIf = EnableFuncIf<!b, -index>; 

// boring traits class: 
template<typename T> 
struct is_int : std::false_type {}; 
template<> 
struct is_int<int> : std::true_type {}; 

#include <iostream> 
// use empty variardic packs to give these two SFINAE functions different signatures: 
template<typename C, EnableFuncIf< is_int<C>::value >...> 
void do_stuff() { 
    std::cout << "int!\n"; 
} 
template<typename C, DisableFuncIf< is_int<C>::value >...> 
void do_stuff() { 
    std::cout << "not int!\n"; 
} 

int main() { 
    do_stuff<int>(); 
    do_stuff<double>(); 
} 

này phân biệt do_stuff từ do_stuff, bởi vì một mất 0 hoặc nhiều UniqueEnum<1> s, và người kia có 0 hoặc nhiều UniqueEnum<-1> s. gcc 4.8 xem xét các gói rỗng khác nhau này để phân biệt.

Tuy nhiên, trong phiên bản mới nhất của clang tôi đã thử, điều này không thành công: nó xử lý hàm với 0 UniqueEnum<1> s giống như hàm 0 UniqueEnum<-1> s.

Có cách giải quyết dễ dàng trong công việc, nhưng tôi tự hỏi nếu kỹ thuật trên của tôi là hợp pháp - làm hai chức năng template s, mà chỉ khác nhau bởi gói tham số biến trống rỗng, thực sự khác nhau?

Trả lời

2

Tôi nghĩ GCC đúng và kỹ thuật của bạn là chính xác. Về cơ bản, vì đối số loại cho C được chỉ định rõ ràng, câu hỏi là liệu:

a. thay thế C ở mọi nơi khác trong chữ ký mẫu chức năng xảy ra đầu tiên, và sau đó loại khấu trừ được thực hiện (mà sẽ dẫn đến một sự thất bại thay thế); hoặc

b. loại khấu trừ được thực hiện đầu tiên, và sau đó thay thế được thực hiện (mà sẽ không dẫn đến một sự thất bại thay thế, bởi vì các gói đối số tương ứng sẽ được sản phẩm nào, và do đó sẽ không có thay thế để thực hiện).

Dường như GCC giả định (1), trong khi Clang giả định (2). Đoạn 14.8.2/2 của tiêu chuẩn C++ 11 quy định cụ thể:

Khi một đối số mẫu rõ ràng được chỉ định, đối số mẫu phải tương thích với danh sách tham số mẫu và phải dẫn đến loại hàm hợp lệ như mô tả dưới đây; nếu không loại trừ khoản không thành công. Cụ thể, các bước sau đây được thực hiện khi đánh giá một quy định rõ ràng mẫu danh sách đối số đối với một hàm template cho với:

- Những lập luận mẫu quy định phải phù hợp với các thông số mẫu bằng hiện vật (ví dụ, chủng loại, không loại , mẫu). Không được có nhiều đối số hơn số tham số trừ khi có ít nhất một tham số là gói tham số mẫu và sẽ có đối số cho mỗi tham số không phải gói. Nếu không, khấu trừ loại không thành công.

- Đối số không phải phù hợp với loại tham số mẫu không nhập tương ứng hoặc phải có thể chuyển đổi thành loại tham số không loại tương ứng như được nêu trong 14.3.2, nếu không thì không thể khấu trừ loại trừ .

- Giá trị đối số mẫu đã chỉ định được thay thế cho các tham số mẫu tương ứng là được chỉ định bên dưới.

Đoạn sau thì nói:

Sau khi thay thế này được thực hiện, điều chỉnh kiểu tham số chức năng được mô tả trong 8.3.5 được thực hiện. [...]

Hơn nữa, đoạn 14.8.2/5 quy định cụ thể:

kết quả thay thế và điều chỉnh chức năng loại được sử dụng như các loại của hàm template cho mẫu luận khấu trừ . [...]

Cuối cùng, đoạn 14.8.2/6 diễn ra như sau:

Tại điểm nhất định trong quá trình trích mẫu luận nó là cần thiết để có một loại chức năng đó tận dụng của tham số mẫu và thay thế các tham số mẫu đó bằng mẫu đối số tương ứng. Điều này được thực hiện khi bắt đầu khấu trừ đối số mẫu khi bất kỳ mẫu được chỉ định rõ ràng đối số được thay thế thành loại hàm và một lần nữa vào cuối trích đối số mẫu khi bất kỳ đối số mẫu nào được suy luận hoặc thu được từ đối số mặc định được thay thế .

Điều này dường như ngụ ý rằng thay thế đầu tiên được thực hiện, sau đó khấu trừ đối số mẫu. Do đó, một sự thất bại thay thế sẽ xảy ra trong cả hai trường hợp và một trong hai mẫu nên được loại bỏ khỏi tập quá tải.

Thật không may, có vẻ như không phải là một đặc điểm kỹ thuật rõ ràng về hành vi nên là gì khi các đối số mẫu được suy luận thay vì được chỉ định rõ ràng.

+0

Điều này chỉ áp dụng khi chúng tôi chỉ định đối số một cách rõ ràng và không suy luận ra nó? (ví dụ, tôi đã thực hiện các chức năng có 'T const &', sau đó thông qua '7' cho nó, các trick không còn hợp pháp?) – Yakk

+0

@Yakk: Trong trường hợp đó tôi không chắc chắn chính xác, nhưng tôi đã đọc thông qua toàn bộ 14.8.2 nhiều lần và dường như với tôi, Tiêu chuẩn không chỉ rõ hành vi nên là gì –

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