4

Есть ли способ специализации функции (скажем, std::swap) для частного класса?Специализация функции для частного класса?

Например, когда я проверить это:

#include <algorithm> 

class Outer 
{ 
    struct Inner 
    { 
     int a; 
     void swap(Inner &other) 
     { 
      using std::swap; 
      swap(this->a, other.a); 
     } 
    }; 
public: 
    static void test(); 
}; 

namespace std 
{ 
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b) 
    { a.swap(b); } 
} 
void Outer::test() 
{ 
    using std::swap; 
    Inner a, b; 
    swap(a, b); 
} 
int main() 
{ 
    Outer::test(); 
    return 0; 
} 

я получаю это:

Test.cpp:20:47: error: 'Inner' is a private member of 'Outer' 
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b) 
              ^
Test.cpp:5:12: note: implicitly declared private here 
    struct Inner 
     ^
Test.cpp:20:64: error: 'Inner' is a private member of 'Outer' 
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b) 
                  ^
Test.cpp:5:12: note: implicitly declared private here 
    struct Inner 
     ^
Test.cpp:20:33: error: 'Inner' is a private member of 'Outer' 
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b) 
           ^
Test.cpp:5:12: note: implicitly declared private here 
    struct Inner 

(Я понимаю, объявляя друга swap, что можно найти с помощью ADL позволяет избежать этой проблемы для swap, но это не имеет никакого отношения к моему вопросу. swap - просто пример.)

+0

ставить «своя своя» (внутренняя, внутренняя) 'inside' Outer'? – TemplateRex

+0

@TemplateRex: Это не будет специализироваться на 'std :: swap', это просто функция nonmember под названием swap. – Mehrdad

+0

Вы не можете специализировать класс, который не отображается. Поскольку 'struct' объявляется с закрытым доступом, только' Outer' может его видеть. Таким образом, вы не можете создать функцию, отличную от Outer-member, которая может ее увидеть, - чтобы вы не специализировались на ней. –

ответ

4

Вы можете добавить friend декларации std::swap<Inner>(Inner&, Inner&) внутри Outer

#include <algorithm> 

class Outer 
{ 
    struct Inner 
    { 
     int a; 
     void swap(Inner &other) 
     { 
      using std::swap; 
      swap(this->a, other.a); 
     } 
    }; 

    friend void std::swap<Inner>(Inner&, Inner&) noexcept; 
public: 
    static void test(); 
}; 

namespace std 
{ 
    template<> void swap<Outer::Inner>(Outer::Inner &a, Outer::Inner &b) noexcept 
    { a.swap(b); } 
} 

void Outer::test() 
{ 
    using std::swap; 
    Inner a, b; 
    swap(a, b); 
} 

int main() 
{ 
    Outer::test(); 
    return 0; 
} 

Live Example

+0

Да, спасибо!=) – Mehrdad

+1

Кстати, «noexcept» был необходим, чтобы заткнуть дальнейшие ошибки компилятора (потому что основной шаблон имеет это также) – TemplateRex

+0

Приятно отметить, спасибо! – Mehrdad

1

Не расширяйте пространство имен std.

Если вы хотите создать функцию подкачки для Inner, сделать его собственную функцию в Outer

#include <algorithm> 

class Outer 
{ 
    struct Inner 
    { 
     int a; 
     void swap(Inner &other) 
     { 
      std::swap(this->a, other.a); 
     } 
    }; 

    static void swap(Inner& a, Inner& b); 

public: 
    static void test(); 
}; 

void Outer::test() 
{ 
    Inner a, b; 
    swap(a, b); 
} 

void Outer::swap(Inner& a, Inner& b) 
{ 
    a.swap(b); 
} 

int main() 
{ 
    Outer::test(); 
    return 0; 
} 
+0

-1 Вы не отвечаете на вопрос. Представьте, что 'std' был' foo' и 'swap' был' bar', теперь я больше не расшифровываю 'std'. Как бы я тогда специализировал «бар»? – Mehrdad

+0

Я ответил на него. Вы не можете создать специализированный метод для функции, которая не может видеть приватный доступ 'struct'. Следовательно, чтобы получить нужную функциональность, создайте закрытую функцию в Outer, называемую 'swap', которая вызывает ваш метод' Inner :: swap'. Так как 'Inner' не отображается вне' Outer', во всяком случае, нет необходимости в специализированной внешней функции. –

+0

Ну, ваш комментарий отвечает на него, но ваш пост нет. Я не согласен с тем, что «нет необходимости», но если это невозможно, это отвечает на мой вопрос ... – Mehrdad

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

  • Нет связанных вопросов^_^