2012-03-09 23 views
5

Tôi đang cố gửi chức năng sort của D làm đối số mẫu cho hàm pipe. Khi tôi sử dụng sort không có đối số mẫu hoạt động: Gửi một chức năng được tạo khuôn mẫu làm đối số cho một chức năng được tạo khuôn mẫu trong D

import std.stdio,std.algorithm,std.functional; 

void main() 
{ 
    auto arr=pipe!(sort)([1,3,2]); 
    writeln(arr); 
} 

Tuy nhiên, khi tôi cố gắng sử dụng sort với một mẫu đối số:

import std.stdio,std.algorithm,std.functional; 

void main() 
{ 
    auto arr=pipe!(sort!"b<a")([1,3,2]); 
    writeln(arr); 
} 

tôi nhận được một lỗi - main.d(5): Error: template instance sort!("b<a") sort!("b<a") does not match template declaration sort(alias less = "a < b",SwapStrategy ss = SwapStrategy.unstable,Range)

Tại sao nó lại xảy ra? sort!"b<a" hoạt động trên chính nó và có cùng các đối số và kiểu trả về là sort, vậy tại sao pipe chấp nhận sort nhưng không phải sort!"b<a"? Và có cú pháp chính xác cho những gì tôi cố gắng làm không?

CẬP NHẬT

OK, tôi đã cố gắng để quấn sort chức năng. Các mã sau đây hoạt động:

import std.stdio,std.algorithm,std.functional,std.array; 

template mysort(string comparer) 
{ 
    auto mysort(T)(T source) 
    { 
     sort!comparer(source); 
     return source; 
    } 
} 

void main() 
{ 
    auto arr=pipe!(mysort!"b<a")([1,3,2]); 
    writeln(arr); 
} 

Vì vậy, tại sao không phải là phiên bản gốc làm việc? có phải vì các thông số mẫu bổ sung sort không?

Trả lời

5

Có vì các tham số mẫu phụ - cụ thể là tham số Range. Vấn đề có thể được giảm xuống

size_t sort2(alias f, Range)(Range range) 
{ 
    return 0; 
} 
alias sort2!"b<a" u; 

Sự kiện sort!"b<a" sẽ không thành công vì phạm vi không được xác định. Hàm gọi sort2!"b<a"([1,2,3]) hoạt động vì tham số [1,2,3] có thể cho trình biên dịch biết phạm vi loại là int[]. Điều này được gọi là "instantiation template function instantiation (IFTI)". Nhưng IFTI chỉ hoạt động khi nó được sử dụng như một hàm. Trong trường hợp sử dụng của bạn, sort!"b<a" được khởi tạo mà không cung cấp tất cả các tham số, do đó có lỗi.

này có thể được cố định bằng cách làm cho đầu vào một hàm theo nghĩa đen, mà chỉ là tương tự như giải pháp mysort của bạn:

auto arr = pipe!(x => sort!"b<a"(x))([1,3,2]); 

Hoặc bạn có thể cung cấp tất cả các thông số mẫu yêu cầu. Điều này làm cho mã rất không thể đọc được mặc dù.

auto arr = pipe!(sort!("b<a", SwapStrategy.unstable, int[]))([1,3,2]); 
+0

Tôi hiểu ... Tôi đã tìm ra mẫu 'pipe', ngầm nhận được kiểu đối số dưới dạng tham số mẫu, nên chuyển tham số đó tới hàm piped đầu tiên, nhưng tôi thấy điều đó không đúng. –

+0

@IdanArye: 'pipe' không bao giờ có thể làm điều đó, bởi vì ta có thể tách nó ra khỏi đối số (' alias pipe! (F) piped; 'và sau đó nhiều dòng sau' piped ([1,2,3]); ') – kennytm

+0

Không nên 'alias'ing như vậy làm cho' piped' một chức năng templated chính nó? –