2012-02-27 33 views
9

Có thể định nghĩa hai lớp mẫu khác nhau (theo số đối số mẫu) có cùng tên không?Mẫu lớp có tên trùng lặp?

Dưới đây là những gì tôi đang cố gắng để làm:

namespace MyNamespace 
{ 

template<class TRet> 
class FunctionObject 
{ 
    typedef typename TRet ReturnType; 
    virtual ReturnType const operator()() const = 0; 
}; 


template<class TRet, class TArg0> 
class FunctionObject 
{ 
    typedef typename TRet ReturnType; 
    typedef typename TArg0 FirstArgumentType; 
    virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
}; 

} 

tôi nhận được một lỗi nhắc đến quá nhiều đối số mẫu vào cuối đóng khung của định nghĩa FunctionObject struct thứ hai.

Tôi biết điều này có thể được thực hiện trong C#, nhưng không chắc chắn về C++. Ai đó có thể làm sáng tỏ một chút ở đây không?

+1

Bạn có ý nghĩa gì trong C#? C# không có mẫu. –

+0

Tôi nghĩ rằng họ có nghĩa là với Generics trong C#. –

+0

Khái niệm về Generics trong C#. – user460762

Trả lời

11

Tôi nghĩ rằng chuyên môn hóa từng phần sẽ làm các trick:

namespace MyNamespace { 

    template<class TRet, class TArg0> 
    class FunctionObject 
    { 
     typedef typename TRet ReturnType; 
     typedef typename TArg0 FirstArgumentType; 
     virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
    }; 

    template<class TRet> 
    class FunctionObject<TRet,void> 
    { 
     typedef typename TRet ReturnType; 
     virtual ReturnType const operator()() const = 0; 
    }; 

} 

Bạn cũng có thể bắt đầu với một mẫu tiểu học với nhiều hơn một tham số.

Tôi nghĩ C++ 11 mẫu variadic của nó cho phép điều này tiện lợi hơn, nhưng tôi đã không có thời gian để chơi với điều này, vì vậy tôi nên để điều đó cho người khác thể hiện.

+0

Vâng, tôi đã nghĩ về nó, nhưng nếu tôi muốn tạo một lớp khác với ba đối số mẫu thì tôi sẽ phải sửa đổi các đối số hiện tại để bao gồm các đối số void cho các đối số không thể áp dụng được. Đề nghị tốt mặc dù. Cảm ơn. – user460762

+0

@ user460762: Có, bạn sẽ phải bắt đầu với số lượng đối số tối đa bạn muốn có thể xử lý. Một số người xử lý điều này bằng cách dựa vào macro meta hackery. Nhưng, như tôi đã nói, các mẫu variadic sẽ thực hiện thủ thuật. – sbi

+1

Tại sao không xác định chỉ một mẫu lớp và cung cấp đối số mặc định cho tham số mẫu thứ hai? – Nawaz

1

Tôi tin rằng một cái gì đó như thế này cũng sẽ làm việc, nhưng có lớp học riêng biệt có thể không là những gì bạn đang tìm kiếm:

namespace MyNamespace 
    { 

     class AbstractFunctionObject 
     { 
     //shared functionality here 
     }; 

     template<class TRet> 
     class ConcreteFunctionObjectA : AbstractFunctionObject 
     { 
     typedef typename TRet ReturnType; 
     virtual ReturnType const operator()() const = 0; 
     }; 


     template<class TRet, class TArg0> 
     class ConcreteFunctionObjectB : AbstractFunctionObject 
     { 
     typedef typename TRet ReturnType; 
     typedef typename TArg0 FirstArgumentType; 
     virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
     }; 

    } 
+0

Trong khi điều này có vẻ thực sự có thể, nó cũng vô ích.Điều gì tốt cho là một lớp cơ sở đa hình rỗng? – sbi

+0

Nó sẽ không trống. Nếu OP chọn đường dẫn này, tôi sẽ di chuyển chức năng sẽ được chia sẻ bởi tất cả các mẫu variadic đến lớp cơ sở. Thật khó để đoán được ý định, vì vậy tôi để trống nó. –

+0

Điều gì có thể có trong một Functor, nhưng 'toán tử()()' cộng với một vài typedef? – sbi

5

Tôi nghĩ bạn có thể làm cho nó làm việc với một lớp mẫu, cung cấp loại mặc định luận cho tham số mẫu thứ hai như:

struct null_type {}; 

template<class TRet, class TArg0 = null_type> 
class FunctionObject 
{ 
    typedef typename TRet ReturnType; 
    typedef typename TArg0 FirstArgumentType; 

    //both functions here 
    virtual ReturnType const operator()() const = 0; 

    virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
}; 
+3

Loại đúng hướng nhưng không hoàn toàn ở đó. Điều này sẽ cho phép sử dụng mẫu với một hoặc hai đối số, nhưng trong câu hỏi ban đầu định nghĩa của hai mẫu có vẻ khá khác nhau (các thành viên khác nhau, chữ ký khác nhau cho 'operator()'). sẽ là con đường để đi. So với câu trả lời của sbi, câu trả lời này có tính năng tốt đẹp khi tạo kiểu * duy nhất * ('null_type' nên là duy nhất) và do đó cho phép sử dụng' void' làm đối số thứ hai của hai chuyên môn đối số, rất hay (+1 cho rằng) –

+0

@ David: Đó thực sự là một thiếu sót nghiêm trọng của ý tưởng của tôi. Tôi nên khắc phục điều đó. – sbi

+0

Chắc chắn là một giải pháp thông minh. Chỉ có một điều cần xem xét với phương pháp này là mọi lớp thừa hưởng lớp/cấu trúc này sẽ phải triển khai tất cả các toán tử rỗng/không áp dụng được. Vì vậy, đó là một thương mại giữa giải pháp thanh lịch (ít tiết) so với gánh nặng ít hơn cho việc cấy ghép trong tương lai. – user460762

6

để hiển thị SBI đã gợi ý variadic mẫu giải pháp:

namespace MyNamespace { 

    template<typename...> FunctionObject; 

    template<class TRet, class TArg0> 
    class FunctionObject<TRet,TArg0> 
    { 
     typedef typename TRet ReturnType; 
     typedef typename TArg0 FirstArgumentType; 
     virtual ReturnType const operator()(FirstArgumentType const &arg) const = 0; 
    }; 

    template<class TRet> 
    class FunctionObject<TRet> 
    { 
     typedef typename TRet ReturnType; 
     virtual ReturnType const operator()() const = 0; 
    }; 

} 

Bây giờ bạn có thể thêm chuyên môn theo bất kỳ thứ tự nào bạn muốn, mà không sửa đổi các mẫu khác (trừ khi số lượng/loại tham số mẫu xung đột).

+0

Yup, '+ 1', điều này đơn giản hơn tôi. Nếu bạn có quyền truy cập vào trình biên dịch hỗ trợ nó. – sbi

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