2012-01-12 26 views
8

Câu hỏi gần như không có ý nghĩa nếu không có ví dụ. Vì vậy, đây là những gì tôi đang cố gắng làm.Tại sao sử dụng gói tham số giá trị tích phân không được phép sau khi gói tham số kiểu trong C++ 11?

Nói chung C++ cho phép như sau:

template<class T, class U, T t, U u> 
void func() {} 

func<char, int, 'A', 10>(); 

Nhưng nó có vẻ như phần mở rộng variadic tự nhiên của nó không hoạt động.

template<class...T, T... t> 
void func() {} 

func<char, int, 'A', 10>(); 

Cả hai clang và g ++ 4.7 từ chối mã trên. Lỗi được hiển thị nơi diễn ra quá trình tạo bản đồ. Nó xuất hiện với tôi rằng hai danh sách variadic nên được phân tích cú pháp một cách rõ ràng bởi vì danh sách đầu tiên có các kiểu và một danh sách khác chỉ có giá trị tích phân.

Nếu ở trên không có nghĩa là để làm việc, tôi nghĩ rằng sau đây sẽ không hoạt động.

template <class Ret, class... Args, Ret (*func)(Args...)> 
class Foo {}; 

Tôi nghĩ mẫu Foo là một điều khá hữu ích để có.

+2

Mẫu 'Foo' sẽ giống như nói' template ', tham số mẫu cuối cùng thực sự không thêm gì cả và do đó hoàn toàn unicecary, sau đó loại có thể được biểu hiện tốt bằng cách sử dụng tham số mẫu (ví dụ 'typedef Ret (* func) (Args ...)' bên trong 'Foo') – Grizzly

+2

@Grizzly: Tham số cuối cùng không cung cấp * type * (có thể được thay thế bởi typedef), nó cung cấp một con trỏ hàm. Một con trỏ hàm được thay thế tại thời gian biên dịch, do đó cho phép tối ưu hóa cross-procedural như inlining. –

+0

@Sumant: Bạn nói đúng là nó có vẻ không rõ ràng, tuy nhiên tôi nghĩ tiêu chuẩn đơn giản chỉ nhằm mục đích đơn giản ở đây bằng cách xác định rằng một gói tham số là "tham số" cuối cùng và không có gì có thể đến sau đó. Điều này làm cho phù hợp dễ dàng hơn. –

Trả lời

8

(Thêm: Trả lời trực tiếp câu hỏi đầu tiên của bạn, bạn cũng có thể biến template<class...T, T... t> void func() {} thành mẫu bên trong. Mẫu này không hoạt động trong g ++ 4.6, nhưng trong clang 3.0, do đó, tôi một thời gian để tìm thấy nó)

Đặt một mẫu bên trong một mẫu:.

template<class ... T> 
struct func_types { 
    template <T ... t> 
    static void func_values() { 
     // This next line is just a demonstration, and 
     // would need to be changed for other types: 
     printf("%c %d\n", t...); 
    } 
}; 

int main() { 
    func_types<char, int> :: func_values<'A', 10>(); 
} 

là một mẫu-bên-một-mẫu chấp nhận được? Cách khác là sử dụng bộ dữ liệu với . . Tôi nghĩ rằng đây là doable, nhưng bạn có thể phải cuộn lớp tuple của riêng bạn (có vẻ như không phải là một make_tuple constexpr

Cuối cùng, bạn có thể có thể thực hiện mẫu Foo của bạn như sau:

template<typename Ret, typename ...Args> 
struct Foo { 
     template< Ret (*func)(Args...)> 
     struct Bar { 
       template<typename T...> 
       Bar(T&&... args) { 
         cout << "executing the function gives: " 
          << func(std::forward(args)...) << endl; 
       } 
     }; 
}; 

int main() { 
    Foo<size_t, const char*> :: Bar<strlen> test1("hi"); 
    Foo<int, const char*, const char*> :: Bar<strcmp> test2("compare","these"); 
} 

Mã sau này nằm trên ideone Để chứng minh, tôi đã triển khai một hàm tạo để chuyển tiếp hàm arg đến hàm đang mã hóa vào mẫu.

+1

Lưu ý rằng việc sử dụng 'Args && ...' là rất tệ, vì việc chuyển tiếp hoàn hảo được hỗ trợ bởi trích mẫu đối số. Tuy nhiên, bạn chỉ định các kiểu đối số một cách rõ ràng, vì vậy điều này là thừa. – Xeo

+0

Có, @Xeo. Tôi nên thay thế 'func (args ...)' bằng 'func (std :: forward (args ...) 'ngược lại giá trị rvalue mất rvalue-ness (giả sử' func' của chúng ta lấy giá trị)? Điều đó có ý nghĩa với tôi. Có một số tinh tế khác tôi đang mất tích? –

+0

.. oh, thực sự, tôi nghĩ rằng tôi cũng cần phải làm cho các nhà xây dựng bản thân một mẫu, để nó được công cụ này khấu trừ. –

2

Bởi vì không ai nghĩ rằng sẽ rất đáng để có tính năng này. mẫu có ý định đơn giản và hiệu quả. atures werent bao gồm một trong hai.

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