специализации в классе
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.09.13 08:49
Оценка:
приветствую!

часто, бывает так, что некоторый шаблон юзается только в приватной части некоторого класса. но, как известно, специализировать шаблоны в классе — нельзя.
но логика подсказывает, что, т.к. этот шаблон юзается только в приватной части класса — было бы логично его не выносить наружу. но приходится...

как вы поступаете в этом случае?

благодарю.


зы
пример, если вдруг кто не понял, о чем речь:
struct type {
private:
   template<bool>
   struct wrapper;

   template<>
   struct wrapper<true> {}; // error: explicit specialization in non-namespace scope 'struct type'
};
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: специализации в классе
От: jazzer Россия Skype: enerjazzer
Дата: 06.09.13 09:04
Оценка: 9 (1) +1
Здравствуйте, niXman, Вы писали:

X>часто, бывает так, что некоторый шаблон юзается только в приватной части некоторого класса. но, как известно, специализировать шаблоны в классе — нельзя.

X>но логика подсказывает, что, т.к. этот шаблон юзается только в приватной части класса — было бы логично его не выносить наружу. но приходится...

X>как вы поступаете в этом случае?


поступаем как требует язык (т.е. специализируем снаружи). Эстетические хотелки — это, конечно, хорошо, но язык у нас такой, какой есть.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: специализации в классе
От: Кодт Россия  
Дата: 06.09.13 09:42
Оценка: 9 (1)
Здравствуйте, niXman, Вы писали:

X>как вы поступаете в этом случае?


Если проблема изоляции реально существует (нужно разорвать зависимости, ускорить компиляцию, и т.п.), то пимпл.
Перекуём баги на фичи!
Re: специализации в классе
От: Chorkov Россия  
Дата: 06.09.13 09:53
Оценка: 9 (1) +1
Здравствуйте, niXman, Вы писали:

X>приветствую!


X>часто, бывает так, что некоторый шаблон юзается только в приватной части некоторого класса. но, как известно, специализировать шаблоны в классе — нельзя.

X>но логика подсказывает, что, т.к. этот шаблон юзается только в приватной части класса — было бы логично его не выносить наружу. но приходится...

X>как вы поступаете в этом случае?


X>благодарю.


// .h
struct type {
private:
   template<bool>
   struct wrapper;
};

// .cpp 
// пользователю не надо знать, как приватный класс специализируется.
template<>
struct type::wrapper<true> {}; 
template<>
struct type::wrapper<false> {};
Re[2]: специализации в классе
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.09.13 09:55
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Если проблема изоляции реально существует (нужно разорвать зависимости, ускорить компиляцию, и т.п.), то пимпл.

нет, эстетики ради.

понял. вопрос закрыт.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: специализации в классе
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.09.13 09:59
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>
C>// .h
C>struct type {
C>private:
C>   template<bool>
C>   struct wrapper;
C>};

C>// .cpp 
C>// пользователю не надо знать, как приватный класс специализируется.
C>template<>
C>struct type::wrapper<true> {}; 
C>template<>
C>struct type::wrapper<false> {}; 

C>


спасибо. но такой вариант не подходит.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: специализации в классе
От: Zhendos  
Дата: 06.09.13 11:48
Оценка: 12 (2)
Здравствуйте, niXman, Вы писали:

X>приветствую!


X>часто, бывает так, что некоторый шаблон юзается только в приватной части некоторого класса. но, как известно, специализировать шаблоны в классе — нельзя.


А точно нельзя? Ваш код конечно не скомпилируется,
а вот такой скомпилируется:

struct type {
private:
  template<typename Fake, bool def>
   struct wrapper;

   template<typename Fake>
   struct wrapper<Fake, true> {
     static const int C = 17;
   };

   template<typename Fake>
   struct wrapper<Fake, false> {
     static const int C = 18;
   };
};
Re[2]: специализации в классе
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.09.13 12:11
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>
Z>struct type {
Z>private:
Z>  template<typename Fake, bool def>
Z>   struct wrapper;

Z>   template<typename Fake>
Z>   struct wrapper<Fake, true> {
Z>     static const int C = 17;
Z>   };

Z>   template<typename Fake>
Z>   struct wrapper<Fake, false> {
Z>     static const int C = 18;
Z>   };
Z>};

Z>

хмм... вариант однако. спасибо, опробую.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: специализации в классе
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.09.13 15:23
Оценка:
что-то тут не так, и не могу понять, что %)

пример сильно порезан, но ситуацию воспроизводит.

template<typename... Types>
struct type {
    template<typename T>
    T get() {
        return checker_helper<void, true>::apply<int>(1); // <<<<<<<<<<<<<<<<<<<<<<
    }

    template<typename, bool>
    struct checker_helper;
    
    template<typename Fake>
    struct checker_helper<Fake, true> {
        template<typename T, typename Map>
        static const T& apply(const Map& map) {
            return 1;
        }
    
        template<typename T, typename Map>
        static T& apply(Map& map) {
            return 2;
        }
    };
    template<typename Fake>
    struct checker_helper<Fake, false> {
        template<typename T, typename Map>
        static const T& apply(const Map&) {}
    
        template<typename T, typename Map>
        static T& apply(Map&) {}
    };
}; // type

int main() {
    type<int, char> t;
    return t.get<int>();
}


prog.cpp: In member function ‘T type<Types>::get()’:
prog.cpp:7:44: error: expected primary-expression before ‘int’
return checker_helper<void, true>::apply<int>(1);
^

пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[4]: специализации в классе
От: Evgeny.Panasyuk Россия  
Дата: 06.09.13 20:30
Оценка: 9 (1)
Здравствуйте, niXman, Вы писали:

X>что-то тут не так, и не могу понять, что %)

X>пример сильно порезан, но ситуацию воспроизводит.

return checker_helper<void, true>::template apply<int>(1);
Re[5]: специализации в классе
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.09.13 20:32
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>
EP>return checker_helper<void, true>::template apply<int>(1);
EP>

да, помогло! спасибо огромное!

подскажи плиз, в каких случаях нужно использовать template перед вызовом функций? и как вообще эта проблема и ее решение называется?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[6]: специализации в классе
От: Шахтер Интернет  
Дата: 06.09.13 22:01
Оценка: 18 (3)
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>>
EP>>return checker_helper<void, true>::template apply<int>(1);
EP>>

X>да, помогло! спасибо огромное!

X>подскажи плиз, в каких случаях нужно использовать template перед вызовом функций? и как вообще эта проблема и ее решение называется?


Ключевое слово template в данном случае не имеет отношение к вызову функции, она квалифицирует следующее за ним имя apply.
Оно указыает компилятору, что это имя некоторого шаблона в класса checker_helper<void, true>. Без такого указания компилятор не может правильно распарзить выражение.
Следующий за apply токен < может быть или началом списка аргументов шаблона, или знаком операции. Не имея квалификации apply не всегда возможно определить, что именно.
Источник этой проблемы -- двойное использование < и > как знаков операций и как шаблонных скобок.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[6]: специализации в классе
От: Evgeny.Panasyuk Россия  
Дата: 06.09.13 22:28
Оценка: 75 (2)
Здравствуйте, niXman, Вы писали:

X>подскажи плиз, в каких случаях нужно использовать template перед вызовом функций? и как вообще эта проблема и ее решение называется?


Смысл примерно такой же как и у typename — нужно сделать "подсказку" компилятору, disambiguate:
//#define WRONG

template<typename T>
void foo(T x)
{
#ifdef WRONG
    x.template value<10>(0);
    x.func<10>(0);
#else
    x.value<10>(0);
    x.template func<10>(0);
#endif
}

struct Value
{
    enum{value=1};
    template<int> void func(int){}
} x;

int main()
{
    foo(x);
}

14.2/4 When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template.
Otherwise the name is assumed to name a non-template. [ Example:

struct X {
    template<std::size_t> X* alloc();
    template<std::size_t> static X* adjust();
};
template<class T> void f(T* p) {
    T* p1 = p->alloc<200>(); // ill-formed: < means less than
    T* p2 = p->template alloc<200>(); // OK: < starts template argument list
    T::adjust<100>(); // ill-formed: < means less than
    T::template adjust<100>(); // OK: < starts template argument list
}


Подробней это описано в C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond: "Appendix B. The typename and template Keywords".
Там проблема с template keyword озаглавлена вот как: "Disambiguating Templates".

Иногда можно избежать необходимости template keyword с помощью переходника, например boost::mpl::apply:
#include <boost/mpl/apply.hpp>

template<typename F>
struct Foo: F::template apply<int>
{
};

// VERSUS:

template<typename F>
struct Bar: boost::mpl::apply<F,int>
{
};

/*****/

struct Identity
{
    template<typename T>
    struct apply
    {
        typedef T type;
    };
};

int main()
{
    Foo<Identity>::type x;
    Bar<Identity>::type y;
}
Re[7]: специализации в классе
От: niXman Ниоткуда https://github.com/niXman
Дата: 07.09.13 06:37
Оценка:
Evgeny.Panasyuk, Шахтер, я понял. спасибо еще раз.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.