2009-02-20 65 views
23

Có rắm não ... Có thể tạo ra thứ gì đó giống như tác phẩm này không?Chuyên môn mẫu lồng nhau

template<int a> struct Foo 
{ 
    template<int b> struct Bar; 
}; 

template<int a> struct Foo<a>::Bar<1> //Trying to specialize Bar 
{ 
}; 

tôi không để làm điều này, nhưng nó sẽ cho phép tôi độc đáo ẩn một số chi tiết thực hiện từ phạm vi không gian tên.

Đề xuất được đánh giá cao!

P .: Tôi quên đề cập rõ ràng rằng chuyên biệt cho Bar trong phạm vi của Foo không được hỗ trợ bởi ngôn ngữ. AFAICS, dù sao đi nữa.

Trả lời

3

Theo những bài viết:

http://www.cpptalk.net/template-member-function-specialization-vt11666.html

bạn không thể chuyên template thành viên của một lớp mẫu không chuyên lớp bên ngoài. Họ không trích dẫn câu và chương. Bản sao của tôi "Ngôn ngữ lập trình C++" không tiết lộ bất cứ điều gì ngay lập tức, và bản sao của tôi tiêu chuẩn là ở nhà (bản sao lưu của tôi, tốt hơn được gọi là "Chris" không phải là xung quanh :-)

+0

Thất vọng. Cảm ơn bạn đã tham khảo! –

+0

ISO14882: 1998 Phần 14.7.3, đoạn 16 là phần mô tả tình huống này. – greyfade

0

Bạn có thể ' t làm điều đó. Tôi đã thử nhiều biến thể. này, tuy nhiên, biên dịch trong GCC 4.1:

template<int a> struct Foo 
{ 
    template<int b> struct Bar; 
    template<1> struct Bar; 
}; 

Chỉnh sửa (sau khi xem xét tiêu chuẩn): Nếu được đưa ra, tuy nhiên, bạn có thể làm điều này:

template <> template <> Foo<1> Bar<1>; 

Nhưng không nếu Foo không phải là chuyên ngành đầu tiên.

12

Có, bạn có thể. Nhưng bạn sẽ cần phải thay đổi cấu trúc cuộc gọi, nhưng chỉ một chút.

Cụ thể, sử dụng mẫu chiến lược để cơ cấu lại việc triển khai chức năng thành viên như một lớp (IS được phép chuyên môn hóa).

Điều này được cho phép miễn là lớp chiến lược không được lồng nhau (và do đó không phụ thuộc vào loại mẫu không chuyên biệt).

ví dụ: (Điều này có lẽ là không đúng cú pháp, nhưng ý tưởng phải rõ ràng)

template <class T> 
class OuterThingThatIsNotSpecialized 
{ 
    template <class U> 
    void memberWeWantToSpecialize(const U& someObj_) 
    { 
    SpecializedStrategy<U>::doStuff(someObj_); 
    } 
}; 

template <class U> 
struct SpecializedStrategy; 

template <> 
SpecializedStrategy<int> 
{ 
    void doStuff(const int&) 
    { 
    // int impl 
    } 
}; 

template <> 
SpecializedStrategy<SomeOtherType> 
{ 
    void doStuff(const SomeOtherType&) 
    { 
    // SOT impl 
    } 
}; 

Đây là cực kỳ hữu ích vì các cuộc gọi đến OuterThingThatIsNotSpecialized với nhiều loại mà không thực hiện tồn tại chỉ đơn giản là sẽ không biên dịch.

PS. Bạn thậm chí có thể sử dụng chiến lược này để một phần chuyên chức năng mẫu, cái gì đó là một C++ khác không thể.

+0

lưu ý rằng anh ta có một lớp mẫu thành viên và không phải là chức năng mẫu thành viên. điều phức tạp hơn đối với lớp mẫu thành viên. bởi vì ví dụ tình bạn không được cấp nữa. –

11

Điều 18, Mục 14.7.3 của tiêu chuẩn 1998 (ISO14882: 1998) cho biết chuyên môn hóa rõ ràng (các lớp bên trong) mẫu thành viên không được phép khi lớp mẫu bên ngoài không chuyên biệt rõ ràng.

0

Như các áp phích trước đã giải thích, điều này là không thể. Tuy nhiên bạn có thể di chuyển các mẫu lồng nhau thành một lớp cơ sở không mẫu:

struct FooBase 
{ 
    template<int b> struct Bar; 
} 
template<int a> struct Foo : public FooBase 
{ 
}; 

struct FooBase::Bar<1> // specializing Bar 
{ 
}; 
0

Như những người khác đã chỉ ra, C++ không cho phép bạn chuyên một lớp lồng nhau nếu bên ngoài lớp mẫu không còn chuyên.Khi tôi đã có một tình huống như thế, tôi đã có thể làm việc xung quanh nó bằng một lớp helper giấu đi trong một không gian tên nội bộ:

namespace internal { 
    template <int a, int b> struct FooBarHelper 
    { /* ... */ }; 
    // Specialization 
    template <int a> struct FooBarHelper<a, 1> 
    { /* specialized version goes here */ }; 
} 

template<int a> struct Foo 
{ 
    template<int b> struct Bar : public internal::FooBarHelper<a, b>; 
}; 

Tất nhiên nó không hoàn toàn như ẩn như bạn có thể thích nó được.

1

Dưới đây là những gì tôi đã làm, mà tôi nghĩ là đơn giản hơn/nhiều inline với những gì bạn đang cố gắng để làm:

Với Helper

template<int a> struct Foo 
{ 
    template<int, int> struct Bar__; 
    template<int b> using Bar = Bar__<b, b>; 
}; 

template<int a> template<int b, int c> struct Foo<a>::Bar__ 
{ 
    // general case 
    const static int x = 0; 
}; 
template<int a> template<int b> struct Foo<a>::Bar__<b, 1> 
{ 
    const static int x = 1; 
}; 

int main(int argc, const char * argv[]) 
{ 
    std::cout << Foo<1>::Bar<0>::x << "\r\n"; // general case - output 0 
    std::cout << Foo<1>::Bar<1>::x << "\r\n"; // specialized case - output 1 
    return 0; 
} 

HOẶC - Các helper có thể bị xóa nếu bạn không nhớ tăng gấp đôi chuyên môn mỗi lần:

Không có người trợ giúp

template<int a> struct Foo 
{ 
    template<int b, int c> struct Bar; 
}; 

template<int a> template<int b, int c> struct Foo<a>::Bar 
{ 
    // general case 
    const static int x = 0; 
}; 
template<int a> template<int b> struct Foo<a>::Bar<b, 1> 
{ 
    const static int x = 1; 
}; 

int main(int argc, const char * argv[]) 
{ 
    std::cout << Foo<1>::Bar<0, 0>::x << "\r\n"; // general case - output 0 
    std::cout << Foo<1>::Bar<1, 1>::x << "\r\n"; // specialized case - output 1 
    return 0; 
} 
Các vấn đề liên quan