Как явно создать экземпляр класса шаблона с вложенным классом с помощью функции Friend (C ++)
Скорее всего, меня уже спрашивали, но все это приближается к пределу моего понимания и понимания C ++, поэтому я 'Я немного медленно понимаю, чтоо чем говорят и что именнопродолжается Позвольте мне просто перейти к коду. Это работает:
template
class Foo
{
struct Bar
{
Bar() {}
~Bar() noexcept {}
Bar(Bar&& b) : Bar() { swap(*this, b); }
friend void swap(Bar& b1, Bar& b2) { /* ... */ }
};
};
template class Foo; // explicit instantiation of Foo with int type
Но как мне переместить определениеswap
внеBar
структурировать тело? Если я сделаю это:
template
class Foo {
struct Bar {
// ...
Bar(Bar&& b) : Bar() { swap(*this, b); } // line 16
// ...
template
friend void swap(typename Foo::Bar&, typename Foo::Bar&);
};
};
template
void swap(typename Foo::Bar& b1, typename Foo::Bar& b2) {} // line 26
template class Foo; // line 31
g ++ (4.7.1, флаги: -Wall -std = c ++ 11) сообщает:
main.cpp: In instantiation of ‘Foo::Bar::Bar(Foo::Bar&&)
[with T = int; Foo::Bar = Foo::Bar]’:
main.cpp:31:16: required from here
main.cpp:16:28: error: no matching function for call to
‘swap(Foo::Bar&, Foo::Bar&)’
main.cpp:16:28: note: candidate is:
main.cpp:26:6: note: template void swap(typename Foo::Bar&,
typename Foo::Bar&)
main.cpp:26:6: note: template argument deduction/substitution failed:
main.cpp:16:28: note: couldn't deduce template parameter ‘T’
Я думаю, код дляswap
также необходимо создать при явной реализацииFoo
, что имеет смысл, но почемут компилятор выяснить, чтоswap(Foo::Bar&...)
должен быть создан? Почему замена шаблона не удалась? Или я все неправильно понял?
ОБНОВЛЕНИЕ 1
С:
template class Foo;
template
void swap(typename Foo::Bar& b1, typename Foo::Bar& b2);
template
class Foo {
struct Bar {
Bar(Bar&& b) : Bar() { swap(*this, b); } // line 19
friend void swap(Foo::Bar& b1, Foo::Bar& b2); // line 20
};
};
template
void swap(typename Foo::Bar& b1, typename Foo::Bar& b2) {} // line 26
template class Foo; // line 29
g ++ (4.7.1, флаги: -Wall -std = c ++ 11) сообщает:
main.cpp: In instantiation of ‘struct Foo::Bar’:
main.cpp:29:16: required from here
main.cpp:20:17: error: template-id ‘swap’ for ‘void swap(Foo::Bar&, Foo::Bar&)’ does not match any template declaration
main.cpp: In instantiation of ‘Foo::Bar::Bar(Foo::Bar&&) [with T = int; Foo::Bar = Foo::Bar]’:
main.cpp:29:16: required from here
main.cpp:19:24: error: no matching function for call to ‘Foo::Bar::Bar()’
main.cpp:19:24: note: candidate is:
main.cpp:19:5: note: Foo::Bar::Bar(Foo::Bar&&) [with T = int; Foo::Bar = Foo::Bar]
main.cpp:19:5: note: candidate expects 1 argument, 0 provided
main.cpp:19:28: error: no matching function for call to ‘swap(Foo::Bar&, Foo::Bar&)’
main.cpp:19:28: note: candidate is:
main.cpp:26:8: note: template void swap(typename Foo::Bar&, typename Foo::Bar&)
main.cpp:26:8: note: template argument deduction/substitution failed:
main.cpp:19:28: note: couldn't deduce template parameter ‘T’
ОБНОВЛЕНИЕ 2
Хорошо, так что это можетэто будет сделано.Петр связан сВывести вложенный класс внутри шаблонано я нене понимаю ответ. Почему не могуswap
быть определенным вне его декларации? Насколько я (неправильно) понимаю вещи, почему могут компилятор создает код дляswap(Foo::Bar&...)
и ссылку на него в коде для явного созданияFoo
? Я совершенно не понял, чтопроисходит? Какие'проблема?
ОБНОВЛЕНИЕ 3
Хорошо, это можетне может быть сделано, потому что, если есть специализации шаблона, компилятор не может 'звонки на гарантиюswap
определяется за пределамиFoo
однозначны, так какFoo::Bar
может быть что-то совершенно другое в конкретной специализации. Я надеюсь я'Я понял это правильно. Но почему неt g ++ предупредите меня об этом, прежде чем я создам явное создание экземпляра?Foo
template
class Foo {
struct Bar {
// ...
Bar(Bar&& b) : Bar() { swap(*this, b); }
// ...
template
friend void swap(typename Foo::Bar&, typename Foo::Bar&);
};
};
template
void swap(typename Foo::Bar& b1, typename Foo::Bar& b2) {}
//template class Foo; // let's comment this explicit instantiation out.
Этот код прекрасно компилируется (g ++ 4.7.1, флаги: -Wall -std = c ++ 11). Но не долженРазве это предупреждает меня, что этот код может вызвать проблемы? Когда я добавляю явную реализациюFoo
проблема нет с самой этой линией, но сswap
код реализован вне. >>Foo