xem xét mãC++ chuyên môn hóa lỗi phân biệt khi đi qua một mảng const
template <class A>
class B;
template <class A>
class B<const A>{};
template <class A, int N>
class B<A[N]>{};
template <class A>
class B<A*>{};
template <class A>
class B<A&>{};
Các instantiations mẫu sau hoạt động tốt:
A<int*&>
A<const int*>
A<int*[3]>
nhưng sau một không hoạt động:
A<const int[3]>
Có một số lý do khiến kết hợp cụ thể này không hợp lệ hoặc có thể là lỗi với g ++ 4.6 .3?
Nhân tiện tôi đã xoay xở để giải quyết vấn đề này bằng cách sử dụng SFINAE và tăng :: disable_if <>, vì vậy ít nhất vấn đề được giải quyết.
EDIT
tôi quên đề cập đến rằng lỗi trong câu hỏi là một mơ hồ lớp mẫu instantiation và nó không thể quyết định giữa sự quá tải cho const hoặc quá tải cho một mảng.
EDIT2
này không có gì để làm với con trỏ, đây là bối cảnh đầy đủ:
Tôi sẽ thông qua cuốn sách C++ Template Metaprogramming và đang làm câu hỏi 2-3 (Chương 2 câu hỏi 3) có nội dung:
Sử dụng các kiểu tính năng đặc điểm để triển khai mẫu lớp type_descriptor, có trường hợp, khi được truyền trực tuyến, in loại tham số mẫu của chúng: LƯU Ý: chúng tôi không thể sử dụng RTTI có cùng tác dụng kể từ, theo đoạn 18.5.1 [lib.type.info] đoạn 7 của tiêu chuẩn, typeid (T) .name() không được bảo đảm để trả lại kết quả có ý nghĩa.
Giải pháp của tôi (bao gồm cả thực hiện giải pháp cho các lỗi biên dịch) như sau:
//QUESTION 2-3
template <class T, class enable = void>
struct type_descriptor
{
std::string operator()() const
{
return "Unknown";
}
};
//specializations for primitive types
#define TYPE_DESC_SPEC(type) template <> \
struct type_descriptor<type,void> \
{std::string operator()() const{return #type;}};
TYPE_DESC_SPEC(int)
TYPE_DESC_SPEC(long)
TYPE_DESC_SPEC(void)
TYPE_DESC_SPEC(short)
TYPE_DESC_SPEC(unsigned char)
TYPE_DESC_SPEC(unsigned short)
TYPE_DESC_SPEC(unsigned long)
//specializations for modifiers *, const, &, and [N]
template <class T>
struct type_descriptor<T&,void>
{std::string operator()(){return type_descriptor<T>()() + " &";}};
template <class T>
struct type_descriptor<T*,void>
{std::string operator()(){return type_descriptor<T>()() + " *";}};
//Replace void with what's in the comment for the workaround.
template <class T>
struct type_descriptor<const T, void/*typename boost::disable_if<boost::is_array<T> >::type*/>
{std::string operator()(){return type_descriptor<T>()() + " const";}};
template <class T>
struct type_descriptor<T(*)(),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)()";}};
template <class T, class U>
struct type_descriptor<T(*)(U),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)(" + type_descriptor<U>()() + ")";}};
template <class T, int N>
struct type_descriptor<T[N],void>
{
std::string operator()()
{
std::stringstream s;
s << type_descriptor<T>()() << " [" << N << "]";
return s.str();
}
};
template <class T>
struct type_descriptor<T[],void>
{std::string operator()(){return type_descriptor<T>()() + " []";}};
//Now overload operator<< to allow streaming of this class directly
template <class T>
std::ostream & operator<<(std::ostream & s, type_descriptor<T> t)
{
return s << t();
}
//END QUESTION 2-3
sử dụng mẫu là:
std::cout << "\nQuestion 2-3 results\n";
std::cout << type_descriptor<int*>() << std::endl;
std::cout << type_descriptor<int*[3]>() << std::endl;
std::cout << type_descriptor<std::string*>() << std::endl;
std::cout << type_descriptor<const int&>() << std::endl;
std::cout << type_descriptor<const int *const&>() << std::endl;
std::cout << type_descriptor<int[4]>() << std::endl;
std::cout << type_descriptor<int(*)()>() << std::endl;
std::cout << type_descriptor<int*&(*)(const char &)>() << std::endl;
std::cout << type_descriptor<int*&>() << std::endl;
std::cout << type_descriptor<int[]>() << std::endl;
std::cout << type_descriptor<const long[]>() << std::endl;
và đầu ra tương ứng là (khi thực hiện giải pháp là trong, nếu không nó không được biên dịch vào cái cuối cùng):
int * int * [3] Unknown * int const & int const * const & int [4] int (*)() int * & (*)(Unknown const &) int * & int [] long const []
Vì vậy, C++ có thể khác iate con trỏ và mảng cho các tham số mẫu, có thể một cách chính xác, đệ quy, các loại hợp chất riêng biệt và xuất kết quả chính xác, ngoại trừ const A[]
. Nó cần được giúp đỡ với điều đó
Hãy đoán điều này - nhưng tôi nghĩ 'const int [3]' phân rã thành 'const int *' –
@AdrianCornish, không phải vậy, hãy xem bản chỉnh sửa. Bên cạnh đó nếu đó là ví dụ hợp lệ thứ ba tôi đưa ra cũng không nên hoạt động. – SirGuy
3rd sẽ hoạt động vì 'const int *' khác với 'int *' - cố gắng (không thành công) để tìm phần tiêu chuẩn ghi lại sự phân rã ;-) –