typedef внутри шаблона
От: al.zatv  
Дата: 15.02.11 11:04
Оценка:
Вот есть функция,параметризуемая шаблоном. Внутри этого шаблона есть длинный тип, который мне надо использовать. Например

template <class Graph>
void fn(Graph &g, typename Graph::vertex_descriptor d1)
{...}

Писать typename Graph::vertex_descriptor тяжело и длинно.

Можно ли сказать так:
template <class Graph>
имей_в_виду_что vertex=typename Graph::vertex_descriptor
void fn(Graph &g, d1,typename Graph::edge_descriptor d2)
{...}

Понятно,что можно сделать ещё один параметр шаблона и задать его значением по умолчанию, но это как-то кажется некрасивым. Может есть ещё какой-то способ?

Заранее благодарен
Re: typedef внутри шаблона
От: ZegSoft Россия  
Дата: 15.02.11 11:34
Оценка:
Здравствуйте, al.zatv, Вы писали:

AZ>Вот есть функция,параметризуемая шаблоном. Внутри этого шаблона есть длинный тип, который мне надо использовать. Например


AZ>template <class Graph>

AZ>void fn(Graph &g, typename Graph::vertex_descriptor d1)
AZ>{...}

AZ>Писать typename Graph::vertex_descriptor тяжело и длинно.


AZ>Можно ли сказать так:

AZ>template <class Graph>
AZ>имей_в_виду_что vertex=typename Graph::vertex_descriptor
AZ>void fn(Graph &g, d1,typename Graph::edge_descriptor d2)
AZ>{...}

AZ>Понятно,что можно сделать ещё один параметр шаблона и задать его значением по умолчанию, но это как-то кажется некрасивым. Может есть ещё какой-то способ?


AZ>Заранее благодарен


Добавь в начало объявления класса:

typedef typename Graph::vertex_descriptor vertex;
Re[2]: typedef внутри шаблона
От: al.zatv  
Дата: 15.02.11 11:38
Оценка:
Здравствуйте, ZegSoft, Вы писали:

ZS>Добавь в начало объявления класса:


ZS>
ZS>typedef typename Graph::vertex_descriptor vertex;
ZS>



не,мопед не мой,лезть в него нельзя. там тем более десятки классов,которые под эту функцию подходят.
Re: typedef внутри шаблона
От: night beast СССР  
Дата: 15.02.11 11:48
Оценка:
Здравствуйте, al.zatv, Вы писали:

AZ>Можно ли сказать так:

AZ>template <class Graph>
AZ>имей_в_виду_что vertex=typename Graph::vertex_descriptor
AZ>void fn(Graph &g, d1,typename Graph::edge_descriptor d2)
AZ>{...}

AZ>Понятно,что можно сделать ещё один параметр шаблона и задать его значением по умолчанию, но это как-то кажется некрасивым. Может есть ещё какой-то способ?


а если учесть что шаблонные параметра по умолчанию для функций не работают, совсем грустно становится.
нормального способа в текущем стандарте нет (про новый не знаю)
можешь сделать
template <class Graph, typename Vertex>
void fn(Graph &g, d1, Vertex d2)

AZ>Заранее благодарен


да вобщем не за что
Re[3]: typedef внутри шаблона
От: ZegSoft Россия  
Дата: 15.02.11 13:21
Оценка:
Здравствуйте, al.zatv, Вы писали:

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


ZS>>Добавь в начало объявления класса:


ZS>>
ZS>>typedef typename Graph::vertex_descriptor vertex;
ZS>>



AZ>не,мопед не мой,лезть в него нельзя. там тем более десятки классов,которые под эту функцию подходят.


Что-то я не понял в чем проблема-то собственно говоря?? Если это не твои классы и изменять их нельзя, то какая тебе разница, какой длины там параметры в этих функциях?? Или в чем фишка-то??
Re[4]: typedef внутри шаблона
От: al.zatv  
Дата: 15.02.11 16:06
Оценка:
Здравствуйте, ZegSoft, Вы писали:

ZS>Что-то я не понял в чем проблема-то собственно говоря?? Если это не твои классы и изменять их нельзя, то какая тебе разница, какой длины там параметры в этих функциях?? Или в чем фишка-то??


Класс не мой, а функция моя! И я хочу её записывать покороче.

Мне надо функцию описать
template <class Graph>
void fn(Graph &g, typename Graph::vertex_descriptor d1,typename Graph::vertex_descriptor d1, typename Graph::edge_descriptor e1,Graph::edge_descriptor e2)
{
и внутри постоянно использую vertex_descriptor
}

Очень длинно, почти нечитабельно. Я хочу укоротить
template <class Graph>
ЗАПОМНИТЬ_ЧТО vertex=typename Graph::vertex_descriptor И edge=typename Graph::vertex_descriptor
void fn(Graph &g, vertex d1,vertex d1, edge d1)
{
и внутри всё будет короче
}

Класс, который полезет под шаблон Graph, не мой. Так что поменять там внутри vertex_descriptor на vertex я не могу. Это вообще-то класс из Boost Graph Library, но это не важно.
Re[2]: typedef внутри шаблона
От: al.zatv  
Дата: 15.02.11 16:12
Оценка:
Здравствуйте, night beast, Вы писали:

NB>а если учесть что шаблонные параметра по умолчанию для функций не работают, совсем грустно становится.

NB>нормального способа в текущем стандарте нет (про новый не знаю)
NB>можешь сделать
NB>template <class Graph, typename Vertex>
NB>void fn(Graph &g, d1, Vertex d2)

О, спасибо за ответ! И спасибо что вникли.
Я вообще-то сделал вот так:
template <class Graph, typename Vertex=typename Graph::vertex_descriptor>
void fn(Graph &g, d1, Vertex d2)

но мне это кажется некрасивым, так как граф может оказаться от одного класса, а вершина от другого.
Re[2]: typedef внутри шаблона
От: al.zatv  
Дата: 15.02.11 16:14
Оценка:
Здравствуйте, night beast, Вы писали:

Сейчас вот написал и понял, что мой вариант точно такой же как и у вас. Только хуже,так как длиннее
Re[5]: typedef внутри шаблона
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.11 00:37
Оценка:
Здравствуйте, al.zatv, Вы писали:

AZ>Мне надо функцию описать

AZ>template <class Graph>
AZ>void fn(Graph &g, typename Graph::vertex_descriptor d1,typename Graph::vertex_descriptor d1, typename Graph::edge_descriptor e1,Graph::edge_descriptor e2)
AZ>{
AZ> и внутри постоянно использую vertex_descriptor
AZ>}



AZ>Очень длинно, почти нечитабельно.

А ты в столбик напиши, и сразу станет читабельно
template <class Graph>
void fn( Graph &g
       , typename Graph::vertex_descriptor d1
       , typename Graph::vertex_descriptor d2
       , typename Graph::edge_descriptor e1
       , typename Graph::edge_descriptor e2 )
{
  //и внутри постоянно использую vertex_descriptor
}


Это — самое простое и очевидное решение твоей надуманной (как мне кажется) проблемы.
Если так уж хочется иметь короткий список параметров и тебе не нужна перегрузка по этим параметрам (т.е. у тебя всего одна функция), то можно так:
template <class Graph, class Vertex, class Edge>
void fn( Graph &g, Vertex d1, Vertex d2, Edge e1, Edge e2 )
{
  BOOST_STATIC_ASSERT(( boost::is_same< Vertex, typename Graph::vertex_descriptor>::value ));
  BOOST_STATIC_ASSERT(( boost::is_same< Edge, typename Graph::edge_descriptor>::value ));
  //и внутри постоянно использую Vertex 
}

Но лично мне решение в столбик нравится больше — оно проще и очевиднее.

ЗЫ И пользуйся кодами разметки, плиз.
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[6]: typedef внутри шаблона
От: Masterkent  
Дата: 16.02.11 05:45
Оценка:
jazzer:

AZ>>Очень длинно, почти нечитабельно.

J>А ты в столбик напиши, и сразу станет читабельно
J>
J>template <class Graph>
J>void fn( Graph &g
J>       , typename Graph::vertex_descriptor d1
J>       , typename Graph::vertex_descriptor d2
J>       , typename Graph::edge_descriptor e1
J>       , typename Graph::edge_descriptor e2 )
J>{
J>  //и внутри постоянно использую vertex_descriptor
J>}
J>

В теле функции можно и typedef-ы завести (формально по текущему стандарту использовать typedef-объявление в определении функции нельзя, но, поскольку данное ограничение — очевидный идиотизм, я не встречал ни одного современного компилятора, который бы не допускал любые typedef-объявления в телах функций).

J>Если так уж хочется иметь короткий список параметров и тебе не нужна перегрузка по этим параметрам (т.е. у тебя всего одна функция), то можно так:

J>
J>template <class Graph, class Vertex, class Edge>
J>void fn( Graph &g, Vertex d1, Vertex d2, Edge e1, Edge e2 )
J>{
J>  BOOST_STATIC_ASSERT(( boost::is_same< Vertex, typename Graph::vertex_descriptor>::value ));
J>  BOOST_STATIC_ASSERT(( boost::is_same< Edge, typename Graph::edge_descriptor>::value ));
J>  //и внутри постоянно использую Vertex 
J>}
J>

Тут ещё надо учитывать, что при автоматическом выведении типов Vertex, Edge и т.д. многим потенциально возможным неявным преобразованиям к Graph::vertex_descriptor и т.д. сразу будет красный свет. Неявные null pointer conversions будут недоступными даже при замене boost::is_same на boost::is_convertible.
Re[6]: typedef внутри шаблона
От: night beast СССР  
Дата: 16.02.11 05:47
Оценка:
Здравствуйте, jazzer, Вы писали:

AZ>>Очень длинно, почти нечитабельно.

J>А ты в столбик напиши, и сразу станет читабельно
J>
J>template <class Graph>
J>void fn( Graph &g
J>       , typename Graph::vertex_descriptor d1
J>       , typename Graph::vertex_descriptor d2
J>       , typename Graph::edge_descriptor e1
J>       , typename Graph::edge_descriptor e2 )
J>{
J>  //и внутри постоянно использую vertex_descriptor
J>}
J>


J>Это — самое простое и очевидное решение твоей надуманной (как мне кажется) проблемы.


позволь не согласиться насчет надуманности.
проблема многословности существует, способствует копипасту, засоряет код.
добавь туда еще темплейт, совсем красиво будет:
typename Graph::template apply<typename Graph::vertex_descriptor,typename Graph::edge_descriptor,>::type e1

еще не начали писать функцию, а уже заняли 7 строчек.

J>Если так уж хочется иметь короткий список параметров и тебе не нужна перегрузка по этим параметрам (т.е. у тебя всего одна функция), то можно так:

J>
J>template <class Graph, class Vertex, class Edge>
J>void fn( Graph &g, Vertex d1, Vertex d2, Edge e1, Edge e2 )
J>{
J>  BOOST_STATIC_ASSERT(( boost::is_same< Vertex, typename Graph::vertex_descriptor>::value ));
J>  BOOST_STATIC_ASSERT(( boost::is_same< Edge, typename Graph::edge_descriptor>::value ));
J>  //и внутри постоянно использую Vertex 
J>}
J>

J>Но лично мне решение в столбик нравится больше — оно проще и очевиднее.

здесь проблема в том, неявные преобразования не работают.
ну и возвращаемый тип таким образом не сделать.
Re[7]: typedef внутри шаблона
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.11 05:57
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>(формально по текущему стандарту использовать typedef-объявление в определении функции нельзя, но, поскольку данное ограничение — очевидный идиотизм, я не встречал ни одного современного компилятора, который бы не допускал любые typedef-объявления в телах функций).


Ну это явная ошибка, наверняка они хотели запретить в объявлении, а не в определении (типа как запрещено объявлять классы, например).

M>Тут ещё надо учитывать, что при автоматическом выведении типов Vertex, Edge и т.д. многим потенциально возможным неявным преобразованиям к Graph::vertex_descriptor и т.д. сразу будет красный свет. Неявные null pointer conversions будут недоступными даже при замене boost::is_same на boost::is_convertible.


+1. Но я так понимаю, это не случай ТС.
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[3]: typedef внутри шаблона
От: night beast СССР  
Дата: 16.02.11 06:05
Оценка:
Здравствуйте, al.zatv, Вы писали:

NB>>а если учесть что шаблонные параметра по умолчанию для функций не работают, совсем грустно становится.

NB>>нормального способа в текущем стандарте нет (про новый не знаю)
NB>>можешь сделать
NB>>template <class Graph, typename Vertex>
NB>>void fn(Graph &g, d1, Vertex d2)

AZ>О, спасибо за ответ! И спасибо что вникли.

AZ>Я вообще-то сделал вот так:
AZ>template <class Graph, typename Vertex=typename Graph::vertex_descriptor>
AZ>void fn(Graph &g, d1, Vertex d2)

AZ>но мне это кажется некрасивым, так как граф может оказаться от одного класса, а вершина от другого.


если нужны ограничения на Vertex, то их можно сделать, но неявного преобразования все равно не будет:
template <class Graph, typename Vertex> 
void fn ( Graph &g, Vertex d1, Vertex d2, typename enable_when_same< Vertex, typename Graph::vertex_descriptor >::type = 0 );
Re[7]: typedef внутри шаблона
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.11 06:25
Оценка:
Здравствуйте, night beast, Вы писали:

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


AZ>>>Очень длинно, почти нечитабельно.

J>>А ты в столбик напиши, и сразу станет читабельно
J>>Это — самое простое и очевидное решение твоей надуманной (как мне кажется) проблемы.

NB>позволь не согласиться насчет надуманности.

NB>проблема многословности существует, способствует копипасту, засоряет код.
NB>добавь туда еще темплейт, совсем красиво будет:
NB>
NB>typename Graph::template apply<typename Graph::vertex_descriptor,typename Graph::edge_descriptor,>::type e1
NB>

NB>еще не начали писать функцию, а уже заняли 7 строчек.
Ну заняли — и ладно, если по-человечески отформатировано, то все вполне читабельно.
Конечно, лучше было бы менее многословно, но правильное форматирование очень помогает.
typename Graph::template apply<
    typename Graph::vertex_descriptor
  , typename Graph::edge_descriptor
  , //...
>::type e1

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

Если так уж надо сокращать запись — надо юзать макросы, других вменяемых способов я не вижу.
Типа
#define VERTEX(x) typename x::vertex_descriptor
#define EDGE(x) typename x::edge_descriptor




J>>Но лично мне решение в столбик нравится больше — оно проще и очевиднее.


NB>здесь проблема в том, неявные преобразования не работают.

их можно выполнить внутри функции, где уже будет доступен typedef.
NB>ну и возвращаемый тип таким образом не сделать.
в смысле — не сделать? Если это должен быть Vertex — так он так и останется. Если нет преобразований, конечно.

В любом случае, как я уже сказал, я реальной альтернативы столбику не вижу.
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[8]: typedef внутри шаблона
От: night beast СССР  
Дата: 16.02.11 06:35
Оценка:
Здравствуйте, jazzer, Вы писали:

NB>>еще не начали писать функцию, а уже заняли 7 строчек.

J>Ну заняли — и ладно, если по-человечески отформатировано, то все вполне читабельно.
J>Конечно, лучше было бы менее многословно, но правильное форматирование очень помогает.
J>
J>typename Graph::template apply<
J>    typename Graph::vertex_descriptor
J>  , typename Graph::edge_descriptor
J>  , //...
>>::type e1
J>

и это только объявление одного аргумента

J>Язык у нас многословный, ничего не поделаешь


я к тому что это не надуманная проблема. то что ничего не поделаешь, это да

J>>>Но лично мне решение в столбик нравится больше — оно проще и очевиднее.


NB>>ну и возвращаемый тип таким образом не сделать.

J>в смысле — не сделать? Если это должен быть Vertex — так он так и останется. Если нет преобразований, конечно.

template <class Graph, typename Vertex>
Vertex fn(Graph &g)


J>В любом случае, как я уже сказал, я реальной альтернативы столбику не вижу.
Re[9]: typedef внутри шаблона
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.11 06:43
Оценка: +1
Здравствуйте, night beast, Вы писали:

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


NB>>>еще не начали писать функцию, а уже заняли 7 строчек.

J>>Ну заняли — и ладно, если по-человечески отформатировано, то все вполне читабельно.
J>>Конечно, лучше было бы менее многословно, но правильное форматирование очень помогает.
J>>
J>>typename Graph::template apply<
J>>    typename Graph::vertex_descriptor
J>>  , typename Graph::edge_descriptor
J>>  , //...
>>>::type e1
J>>

NB>и это только объявление одного аргумента

J>>Язык у нас многословный, ничего не поделаешь


NB>я к тому что это не надуманная проблема. то что ничего не поделаешь, это да


Ну, если этот крокодил повторяется и зависит только от графа, то его можно и в метафункцию упаковать, в результате получится нечто вроде
template<class Graph>
struct MF
  : Graph::template apply<
        typename Graph::vertex_descriptor
      , typename Graph::edge_descriptor
      , //...
    >
{};

//...
typename MF<Graph>::type e1

короче уже не сделать, боюсь
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: typedef внутри шаблона
От: andrey.desman  
Дата: 21.02.11 10:07
Оценка:
Здравствуйте, al.zatv, Вы писали:

AZ>Вот есть функция,параметризуемая шаблоном. Внутри этого шаблона есть длинный тип, который мне надо использовать. Например


AZ>template <class Graph>

AZ>void fn(Graph &g, typename Graph::vertex_descriptor d1)
AZ>{...}

AZ>Писать typename Graph::vertex_descriptor тяжело и длинно.


AZ>Можно ли сказать так:

AZ>template <class Graph>
AZ>имей_в_виду_что vertex=typename Graph::vertex_descriptor
AZ>void fn(Graph &g, d1,typename Graph::edge_descriptor d2)
AZ>{...}

AZ>Понятно,что можно сделать ещё один параметр шаблона и задать его значением по умолчанию, но это как-то кажется некрасивым. Может есть ещё какой-то способ?


template<typename T>
struct G
{
    typedef typename T::vertex_descriptor vertex;
    typedef typename T::edge_descriptor edge;

    static void fn(T &g, vertex d1, vertex d2, edge e1, edge e2)
    { }
};
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.