2015-08-29 4 views
1

Недавно я начал использовать шаблон. И я просто сбрасываю ошибку компиляции.Сделать Friend конструктором класса шаблона

У меня есть шаблон шаблона Foo, который принимает значение boolean B в качестве параметра шаблона. И я пытаюсь сделать друг, в instentiation из Foo с аргументом шаблона b, конструктор другого экземпляра Foo с аргументом !b с этим кодом:

template<bool B> 
class Foo 
{ 
public: 
    Foo(Foo<!B>&); 
private: 
    friend Foo<!B>::Foo(Foo<B>&); 
}; 

Компилятором вернуть мне эти ошибки:

test.cpp:22:18: error: C++ requires a type specifier for all declarations 
     friend Foo<!B>::Foo(Foo<B>&); 
     ~~~~~~  ^
test.cpp:22:18: error: constructor cannot have a return type 
     friend Foo<!B>::Foo(Foo<B>&); 
         ^~~ 
2 errors generated. 

Я скомпилировал его с помощью следующей команды: clang++ -std=c++11 foo.cpp на Windows.

Я действительно не понимаю, как заставить его работать, любая помощь, чтобы понять, что не так, ценится.

ответ

4

Я комментировал чужой ответ, и они попросили меня вставить мой анализ здесь.

Я думаю, что ваш случай проблематичен, потому что Foo<true> имеет объявление друга для функции члена Foo<false>, которая в свою очередь относится к функции члена Foo<true>. Хотя члены, соответственно, объявляются перед функциями-членами, этот тип циркулярной ссылки не поддерживается компиляторами. GCC жалуется на конкретизации

main.cpp: In instantiation of 'class Foo<false>': 
main.cpp:9:12: required from 'class Foo<true>' 
main.cpp:15:49: required from here 
main.cpp:9:12: error: invalid use of incomplete type 'class Foo<true>' 
    friend Foo<!B>::Foo(Foo<B>&); 

Это сообщение об ошибке немного сбивает с толку, поскольку она предполагает, что неполные типы не могут быть использованы с ::, что неправильно. Определяемый класс может использоваться с ::, даже если он еще не завершен. Класс, который создается экземпляром, по-разному обрабатывается GCC, чем класс, который определяется, и ссылка на класс, который создается экземпляром в квалифицированном имени, по-видимому, не поддерживается GCC.

У нас есть DR о таких циклических ссылках, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287, которые, как представляется, делают это законным, но, как говорится в заключительном заявлении, «Это требует работы», поэтому GCC имеет право отклонить ваш код, который я бы сказал. Чтобы добавить к этой путанице, у нас также есть явное правило для имен, используемых в объявлениях функций друга, которые не упоминаются в DR287, и его «как будто» сделает ваш код плохо сформированным, потому что точка создания экземпляра Foo<!B> непосредственно перед точка инстанцирования Foo<B> и, если мы не применим правило в DR287, не может увидеть объявление конструктора Foo<B>.

Классы или функции класса могут быть объявлены в шаблоне класса. При обработке шаблона, имена его друзей рассматриваются как если специализация была объявлена ​​явно в его точке конкретизации


Независимо от этого, есть еще одна проблема под рукой: Является ли Foo<!B>::Foo(Foo<B>&); со ссылкой на конструктор? Это ссылка на конструктор, если она ссылается на введенное имя класса, которое компилятор тогда должен рассматривать как конструктор в этих constexts. Поэтому компилятор должен решить Foo<!B>::Foo.Но Foo<!B> - зависимый тип, поэтому компилятор не может заглянуть в него, чтобы решить, какое это имя (помните, что разрешено struct A { int A; }, и компилятор должен убедиться, что он не в такой ситуации). Я думаю, по этим причинам, cland не удается разобрать ваш шаблон, потому что он смущен относительно того, что означает friend Foo<!B>::Foo(Foo<B>&).

Я считаю, сама (без учета вопросов конкретизации) шаблон должен быть хорошо образован, потому что компилятор может просто задержать поиск по Foo<!B>::Foo и принять его как не тип, который он на самом деле является (Конструкторы).

+0

Благодарим вас за то, что вы очень информативный ответ. Таким образом, мой единственный способ пойти - это объявить, что все кластерное задание шаблона является другом, не так ли? – Poroing

+0

@user правильный, я так думаю. Но, возможно, вы можете переместить код, который нуждается в частном доступе к функции-члене и подружиться с функцией-членом. –

+0

О, мне нравится, что вы идете переместить код в другую функцию-член, я посмотрю, смогу ли я сделать что-то хорошее , Спасибо вам большое. – Poroing

Смежные вопросы