C++11::templates::compilation failure
От: syvyi Россия  
Дата: 22.02.13 17:35
Оценка: -1
Почему не компилируется. Объяснить.
template< unsigned v = 10 >
class a
{
    public:
    class b
    {
        std::vector< char > seq;
        int n;
        friend void std::swap<>( b &, b & );
    };
};
namespace std
{
    template<unsigned h>
    void swap(
                a<h>::b & lhs,
                a<h>::b & rhs
            )
    {
        std::swap( lhs.vec, rhs.vec );
        std::swap( lhs.n, rhs.n );        
    }
}

int main()
{
a<>::b o1();
a<>::b o2();
std::swap(o1,o2);
}

разметку добавить. — Кодть
23.02.13 19:46: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
c++11 templates
Re: C++11::templates::compilation failure
От: zaufi Земля  
Дата: 22.02.13 21:08
Оценка: 18 (2) :)
Здравствуйте, syvyi, Вы писали:

S>Почему не компилируется. Объяснить.


почему инструкцию не читать? Объяснить!

23.02.13 19:46: Перенесено из 'C/C++'
Re[2]: C++11::templates::compilation failure
От: zaufi Земля  
Дата: 22.02.13 21:10
Оценка: :)
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, syvyi, Вы писали:


S>>Почему не компилируется. Объяснить.


Z>почему инструкцию не читать? Объяснить!


и это (ВСЕ) хорошо бы прочитать! читать!
Re: C++11::templates::compilation failure
От: Кодт Россия  
Дата: 24.02.13 19:52
Оценка:
Здравствуйте, syvyi, Вы писали:

S>Почему не компилируется. Объяснить.


Затруднюсь сказать, как правильно написать шаблон свободной функции, принимающей вложенный класс шаблонного класса. Может быть, что вообще никак.
А вот как исправить — пожалуйста.
template<int N>
class A
{
public:
    class B
    {
        int x;
        std::vector<char> y;
    public:
        void swap(B& other); // во-первых, пригодится; во-вторых, иллюстрация, как вынести код за объявление класса
        friend void swap(B& lhs, B& rhs) { lhs.swap(rhs); } // тоже пригодится, хотя это исключительно для ADL
    };
};

template<int N> void A<N>::B::swap(B& other) // этот код можно было и проинлайнить в объявлении класса
{
    using std::swap; // чтобы помочь ADL - знать, где искать
    swap(x, other.x);
    swap(y, other.y);
}

namespace std
{
    template<int N> void swap(typename ::A<N>::B& lhs, typename ::A<N>::B& rhs) // это перегрузка, а не специализация
    {
        lhs.swap(rhs);
    }
}

int main()
{
    A<1>::B p, q;
    swap(p,q); // это колдунство, основанное на тонком месте, если не сказать - дефекте, стандарта (функция swap лежит ни в ::, ни в std::)
    std::swap(p,q);
}
Перекуём баги на фичи!
Re: C++11::templates::compilation failure
От: rg45 СССР  
Дата: 24.02.13 20:21
Оценка: 64 (1)
Здравствуйте, syvyi, Вы писали:

S>Почему не компилируется. Объяснить.

S>
  Пример
S>template< unsigned v = 10 >
S>class a
S>{
S>    public:
S>    class b
S>    {
S>        std::vector< char > seq;
S>        int n;
S>        friend void std::swap<>( b &, b & );
S>    };
S>};
S>namespace std
S>{
S>    template<unsigned h>
S>    void swap(
S>                a<h>::b & lhs,
S>                a<h>::b & rhs
S>            )
S>    {
S>        std::swap( lhs.vec, rhs.vec );
S>        std::swap( lhs.n, rhs.n );        
S>    }
S>}

S>int main()
S>{
S>a<>::b o1();
S>a<>::b o2();
S>std::swap(o1,o2);
S>}
S>


Складывается впечатление, что ты троллишь, потому что твой пример выглядит как сборник избитых замусоленных тем:

  1. Специализацию шаблонной функции std::swap, которую ты объявляешь дружественной классу b не возможно определить (и даже объявить) за пределами шаблонного класса a, поскольку она является зависимой от шаблонного параметра и за пределами этого шаблонного класса эта специализация не может быть полной, а частичные специализации для шаблонных функций, как известно, никогда не поддерживались и не поддерживаются сейчас. Это замусоленная тема номер раз;

  2. Как следствие, определение этой специализации также невозможно сделать внутри классов a и b, поскольку согласно стандарту, в случаях, когда определение явной специализации выполняется за пределами пространства имен, в котором объявлен основной шаблон (std в данном случае), эта специализация должна быть предварительно объявлена в этом пространстве имен. Это замусоленная тема номер два;

  3. Невозможность определения дружественной функции является хорошей иллюстрацией того, почему не нужно злоупотреблять вложенностью классов. Это замусоленная тема номер три;

  4. Перегруженная шаблонная функция swap, которую ты определяешь ниже в пространстве имен std, не является дружественной классу a<>::b, поскольку не соответствует объявленной ранее дружественной специализации;

  5. Автовыведение типов параметров не будет работать для этой шаблонной функции, поскольку компиляторы не могут выводить внешний тип по внутреннему. Это еще одна избитая тема;

  6. Конструкции вида:
    a<>::b o1();
    a<>::b o2();
    давно уже стали притчей во языцех, поскольку не являются определением локальных переменных, а являются объявлением глобальных функций.

Ты специально что ли собирал все эти грабли в один сарай?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: C++11::templates::compilation failure
От: rg45 СССР  
Дата: 25.02.13 00:40
Оценка: +1
Здравствуйте, Кодт, Вы писали:

К>
К>namespace std
К>{
К>    template<int N> void swap(typename ::A<N>::B& lhs, typename ::A<N>::B& rhs);
К>}

К>int main()
К>{
К>    A<1>::B p, q;
К>    std::swap(p,q); // couldn't deduce template parameter ‘N’
К>}
К>


Неа, не взлетит. Я помню, тебе уже неоднократно приходилось разбирать и разъяснять подобные случаи. Не может компилятор для этой перегрузки автоматически вывести шаблонный параметр N: http://ideone.com/3WqFlE. А твой предыдущий пример компилируется за счет того, что вместо этой перегрузки выбирается стандартный swap<T>(T&,T&) из библиотеки.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: C++11::templates::compilation failure
От: rg45 СССР  
Дата: 25.02.13 07:12
Оценка:
Здравствуйте, rg45, Вы писали:

R>...А твой предыдущий пример компилируется за счет того, что вместо этой перегрузки выбирается стандартный swap<T>(T&,T&) из библиотеки.


Вот она, обратная сторона SFINAE
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: C++11::templates::compilation failure
От: Кодт Россия  
Дата: 25.02.13 07:51
Оценка:
Здравствуйте, rg45, Вы писали:

R>Неа, не взлетит. Я помню, тебе уже неоднократно приходилось разбирать и разъяснять подобные случаи. Не может компилятор для этой перегрузки автоматически вывести шаблонный параметр N: http://ideone.com/3WqFlE. А твой предыдущий пример компилируется за счет того, что вместо этой перегрузки выбирается стандартный swap<T>(T&,T&) из библиотеки.


Ай, блин, точно.
Тогда остаётся последний, военный способ.
В местах вызовов вместо std::swap(p,q); писать using std::swap; swap(p,q); — чтобы работал ADL и вызывалась френд-функция, живущая в трещине между мирами.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.