2011-02-09 29 views
13

Các mã sau đây tạo ra một lỗi biên dịch trong Xcode:Implicit Template Parameters

template <typename T> 
struct Foo 
{ 
    Foo(T Value) 
    { 
    } 
}; 

int main() 
{ 
    Foo MyFoo(123); 
    return 0; 
} 

error: missing template arguments before 'MyFoo'

Thay đổi Foo MyFoo(123);-Foo<int> MyFoo(123); sửa chữa vấn đề này, nhưng không nên trình biên dịch có thể tìm ra thích hợp loại dữ liệu?

Đây có phải là lỗi trình biên dịch hay tôi hiểu nhầm các tham số mẫu ẩn không?

Trả lời

11

Các nhà xây dựng có thể về mặt lý thuyết suy luận kiểu của đối tượng nó được xây dựng, nhưng tuyên bố:

Foo MyFoo(123); 

Được bố trí không gian tạm MyFoo và phải biết loại đầy đủ điều kiện của MyFoo để biết cần bao nhiêu không gian.

Nếu bạn muốn tránh gõ (ví dụ với ngón tay) tên của một mẫu đặc biệt phức tạp, xem xét sử dụng một typedef:

typedef std::map<int, std::string> StringMap; 

Hoặc trong C++ 0x bạn có thể sử dụng từ khóa auto để có sử dụng loại suy luận của trình biên dịch - mặc dù nhiều người cho rằng dẫn đến ít mã dễ đọc hơn và dễ bị lỗi hơn, bản thân tôi trong số đó. ; P

+5

nếu nó có thể suy ra các loại, nó có thể suy ra các không gian. –

+6

Nó có thể suy ra loại cho cuộc gọi đến hàm tạo, nhưng không thể cho không gian lưu trữ. Nếu bạn định nghĩa một biến chỉ đơn giản là 'Foo', nó có thể giữ cả hai' Foo 'và' Foo '? Hay nó luôn luôn biết bí mật một 'Foo ' trong trái tim của nó? Nếu biến là 'const' thì nó có thể được thực hiện, vì giá trị không thể được gán lại, nhưng sau đó chúng ta sẽ có các quy tắc từ vựng khác nhau cho' const T' so với 'T' và sự tàn phá lớn sẽ xảy ra. –

7

trình biên dịch có thể hình dung ra kiểu mẫu tham số duy nhất cho chức năng templated, không cho các lớp/struct

+3

Sau khi tất cả, có một lý do cho hàm 'std :: make_pair (T t, U u)' mặc dù chúng ta đã có lớp 'std :: pair '. –

2

Nó không phải là một lỗi, nó không tồn tại tính năng. Bạn phải chỉ định đầy đủ các đối số mẫu lớp/cấu trúc trong quá trình khởi tạo, luôn luôn, các kiểu không được suy ra vì chúng có thể là cho các mẫu hàm.

2

trình biên dịch có thể suy ra các mẫu đối số trường hợp như vậy:

template<typename T> 
void fun(T param) 
{ 
    //code... 
} 

fun(100); //T is deduced as int; 
fun(100.0); //T is deduced as double 
fun(100.0f); //T is deduced as float 

Foo<int> foo(100); 
fun(foo); //T is deduced as Foo<int>; 

Foo<char> bar('A'); 
fun(bar); //T is deduced as Foo<char>; 

Trên thực tế mẫu khấu trừ đối số là một vấn đề lớn. Đọc bài viết này tại ACCU:

The C++ Template Argument Deduction

0

Nó làm cho rất nhiều ý nghĩa nó là như thế này, như Foo không phải là một lớp học, chỉ Foo<T> nơi T là một loại.

Trong C++ 0x bạn có thể sử dụng tự động, và bạn có thể tạo một hàm để tạo cho bạn một Foo, hãy gọi nó là foo (chữ thường thấp hơn f). Sau đó, bạn sẽ làm gì

template<typename T> Foo<T> foo(int x) 
{ 
    return Foo<T>(x); 
} 

auto myFoo = foo(55); 
+0

Có thể bạn muốn nói: "mẫu Foo foo (T x)"? –

2

Trong C++ 11 bạn có thể sử dụng decltype:

int myint = 123; 
Foo<decltype(myint)> MyFoo(myint);