Làm thế nào để chuyển tiếp khai báo một lớp mẫu C ++?


101

Đưa ra một lớp mẫu như sau:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

Làm cách nào để ai đó có thể chuyển tiếp khai báo lớp này trong tệp tiêu đề?

Câu trả lời:


104

Đây là cách bạn sẽ làm điều đó:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings;

template<typename Type, typename IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

Lưu ý rằng mặc định nằm trong khai báo chuyển tiếp chứ không phải trong định nghĩa thực tế.


Có thể khai báo chuyển tiếp một lớp có các giá trị mặc định được liệt kê trong định nghĩa của nó. Hãy xem câu trả lời của tôi.
Elliott

Tôi không đồng ý. Tiêu chuẩn nói: "Một tham số mẫu sẽ không được cung cấp đối số mặc định bởi hai khai báo khác nhau trong cùng một phạm vi" . Và tôi không tìm thấy gì về mặc định chỉ trong khai báo đầu tiên. Ngoài ra, mã với khai báo chuyển tiếp và mặc định trong định nghĩa biên dịch và chạy thành công. Bạn có chắc chắn về những gì bạn đang tuyên bố? Bạn có thể cung cấp một báo giá từ tiêu chuẩn?
olek stolar

@Elliott Có vẻ như đó là sự thật. Tiêu chuẩn [17.1.9] nói: "Một đối số mẫu mặc định có thể được chỉ định trong khai báo mẫu." Không phải là, nhưng có thể được. Vì vậy, tôi không hiểu tại sao các câu trả lời khác cho rằng nó phải có trong khai báo đầu tiên.
olek stolar

Và có vẻ thuận tiện hơn nhiều khi có các giá trị mặc định trong định nghĩa.
olek stolar

8

Bạn có thể khai báo các đối số mặc định cho một mẫu chỉ cho khai báo đầu tiên của mẫu. Nếu bạn muốn cho phép người dùng chuyển tiếp khai báo mẫu lớp, bạn nên cung cấp tiêu đề chuyển tiếp. Nếu bạn muốn chuyển tiếp khai báo mẫu lớp của người khác bằng cách sử dụng mặc định, bạn đã không gặp may!


Có thể khai báo chuyển tiếp một lớp có các giá trị mặc định được liệt kê trong định nghĩa của nó. Hãy xem câu trả lời của tôi.
Elliott

Tôi không đồng ý. Tiêu chuẩn nói: "Một tham số mẫu sẽ không được cung cấp đối số mặc định bởi hai khai báo khác nhau trong cùng một phạm vi" . Và tôi không tìm thấy gì về mặc định chỉ trong khai báo đầu tiên. Ngoài ra, mã với khai báo chuyển tiếp và mặc định trong định nghĩa biên dịch và chạy thành công. Bạn có chắc chắn về những gì bạn đang tuyên bố? Bạn có thể cung cấp một báo giá từ tiêu chuẩn?
olek stolar

3

Bạn có thể khai báo một lớp mẫu có định nghĩa nêu rõ các đối số mặc định, nhưng bất kỳ lúc nào bạn tham chiếu đến lớp, bạn phải bao gồm tất cả các đối số của nó cho đến khi định nghĩa được giới thiệu.

ví dụ. Hãy sử dụng std::vectormà không bao gồm nó (đối số thứ hai của std::vectorđược xác định với một mặc định):

namespace std
{
    template<typename, typename>
    class vector;
}

#include <iostream>

template <typename S, typename T>
void Foo (const std::vector<S,T> & vector)
{
    std::cout << "do vector stuff, eg., display size = "
        << vector.size() << std::endl;
}

template <typename T>
void Foo (const T & t)
{
    std::cout << "do non-vector stuff..." << std::endl;
}

Sau đó, chúng tôi có thể sử dụng nó mà không cần bao gồm vectơ, ví dụ:

int main()
{
    Foo(3);
}

Và chúng ta có thể sử dụng nó với std::vector , ví dụ:

#include <vector>

// Now the compiler understands how to handle
// std::vector with one argument
// (making use of its default argument)

int main()
{
    Foo(std::vector<int>(3));
}

Tôi chưa kiểm tra các tiêu chuẩn, nhưng điều này hoạt động trên clang/ gccvới -std=c++98tối đa -std=c++17, vì vậy nếu nó không phải là tiêu chuẩn chính thức thì có vẻ như không chính thức.


Có thể bạn quên dấu ngoặc nhọn trống Foo<> foo;.
olek stolar

@ OleksijPlotnyc'kyj bạn nói đúng. Cảm ơn. Tôi đã xóa phần bổ sung đó.
Elliott
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.