Блог пользователя pisarik

Автор pisarik, 14 лет назад, По-русски
template <typename _Ty>
class A
{
public:
	A(){}
	~A(){}
private:
	static bool Equals(const _Ty &a, const _Ty &b) { return a == b;}
};
//специализируем для char*
template<>
bool A<char*>::Equals(const char* &a, const char* &b){
	return !strcmp(a, b);	
}

Но получим такую ошибку 'A<_Ty>::Equals' : unable to match function definition to an existing declaration. Чуть поколупавшись, оказалось, что работает вот такой вариант:

template<>
bool A<char*>::Equals(char* const &a, char* const &b){ //WHY
	return !strcmp(a, b);	
}

char* const &a — сатана какой-то:DDD

UPD. В идеале надо было бы сделать Equals public'ом и friend'ом, а то немного не логично вышло, не ругайте:)

  • Проголосовать: нравится
  • +7
  • Проголосовать: не нравится

»
14 лет назад, скрыть # |
← Rev. 4  
Проголосовать: нравится +7 Проголосовать: не нравится

Equals должен принимать ссылку на константный _Ty. Подставляем _Ty = const char *, получаем: Equals должен принимать ссылку на константный const char *. В типе const char * квалификатор const относится не к самому указателю, а к указуемым данным, то есть, это указатель на константный char. Совмещая вместе, получаем: Equals должен принимать ссылку на константный указатель на константный char. Это записывается так: const char * const &. То есть, специализация должна быть

template<>
bool A<const char*>::Equals(const char * const& a, const char * const& b){
    return !strcmp(a, b);
}

Для справки:

  • char * — указатель на char
  • const char * — указатель на константный char
  • char * const — константный указатель на char
  • const char * const — константный указатель на константный char
  • »
    »
    14 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Спасибо, разобрался:) А могли бы еще пояснить, почему эти записи эквивалентны const char* и char const*?

    • »
      »
      »
      14 лет назад, скрыть # ^ |
      ← Rev. 2  
      Проголосовать: нравится +6 Проголосовать: не нравится

      Просто потому что они эквивалентны по определению (так написано в стандарте языка). Второй вариант предпочитают любители читать тип «справа налево» (т.е.,

      char    const          *               const          &
      char <- константный <- указатель на <- константный <- ссылка на

      ), но, по-моему, выглядит он немного дико.

»
14 лет назад, скрыть # |
 
Проголосовать: нравится +2 Проголосовать: не нравится

Я сам никогда так не писал, но вот моя догадка. Такое определение

static bool Equals(const _Ty &a, const _Ty &b)

предполагает, что аргументы a и b должны быть неизменного типа, потому что const. Следовательно, когда мы пишем

A<char*>::Equals

мы тем самым указываем, что a и b должны быть неизменными пойнтерами, то есть char* const. Первый же вариант, const char* &a, не подходит под описание, потому что определяет тип как указатель на неизменяемый char, что, образно говоря, выглядит как-то так: (const char)* &a.

»
14 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

В идеале надо было бы сделать Equals public'ом и friend'ом
Если функция — friend, то неважно, public она, protected или private.