Как явно создать экземпляр класса шаблона с вложенным классом с помощью функции 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

Ответы на вопрос(2)

Ваш ответ на вопрос