[Предложение] Вывод типа шаблона класса из конструктора
От: _NN_ www.nemerleweb.com
Дата: 13.11.12 12:22
Оценка:
Никто не знает планируется ли такая фишка в будущем ?

template<typename T>
struct A
{
  A(T) {}
};

A x(1); // Вывод T = int


Может в С++11 можно что-то сделать ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: [Предложение] Вывод типа шаблона класса из конструктора
От: Erop Россия  
Дата: 13.11.12 12:55
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Может в С++11 можно что-то сделать ?


Канешно. Макорос подойдёт?
#define AUTO_DEFINE_AS( TEMPLATE_NAME, VAR, INIT_WITH ) \
    TEMPLATE_NAME<decltype(INIT_WITH)> VAR(INIT_WITH) 

AUTO_DEFINE_AS( A, x, 1 );


или так:
template<typename T> A<T> as_A( const T& arg ) { return arg; }
auto x1 = as_A( 1 );


Ты расскажи чего тебе и для чего на самом деле надобно-то, а то может уже есть готовое?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: [Предложение] Вывод типа шаблона класса из конструктора
От: _NN_ www.nemerleweb.com
Дата: 13.11.12 13:31
Оценка:
Здравствуйте, Erop, Вы писали:

Ну да, совсем про auto забыл =)
Хотя конечно уточнение типа было бы тоже хорошо
A<auto> x(1);


E>Ты расскажи чего тебе и для чего на самом деле надобно-то, а то может уже есть готовое?..


Скажем типичный пример:
vector<int> v = {1,2,3};

sort(v.begin(), v.end(), less<int>());


Вот тут хотелось бы получить вывод шаблонного типа.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: [Предложение] Вывод типа шаблона класса из конструктора
От: hotdox  
Дата: 13.11.12 13:51
Оценка: +1
Здравствуйте, _NN_, Вы писали:

_NN>Никто не знает планируется ли такая фишка в будущем ?


_NN>
_NN>template<typename T>
_NN>struct A
_NN>{
_NN>  A(T) {}
_NN>};

_NN>A x(1); // Вывод T = int
_NN>


_NN>Может в С++11 можно что-то сделать ?


Можно как-то так:

template<typename T>
struct A
{
      A(T) {}
};

template<typename T>
A<T> makeA(T t)
{
    return A<T>(t);
}

int main()
{
        auto a = makeA(1);
}
Re[2]: [Предложение] Вывод типа шаблона класса из конструктора
От: _NN_ www.nemerleweb.com
Дата: 13.11.12 14:09
Оценка:
Здравствуйте, hotdox, Вы писали:

Это обход, а не решение.

Хотя, наверное можно попробовать в рамках С++11 типа такого.
Только я где-то тут ошибся и код не собирается
#include <utility>
 
template<template<typename...> class T, typename... Args>
T<Args...>&& Create(Args... args)
{
    return std::move(T<Args...>(std::forward(args...)));
}
 
template<typename T>
class A
{
    A(T) {}
};
 
int main()
{
  A<int> a = Create<A>(1);
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: [Предложение] Вывод типа шаблона класса из конструктора
От: rg45 СССР  
Дата: 13.11.12 15:05
Оценка: 8 (1) +1
Здравствуйте, _NN_, Вы писали:

_NN>Хотя, наверное можно попробовать в рамках С++11 типа такого.

_NN>Только я где-то тут ошибся и код не собирается
_NN>[...]

template<template<typename...> class T, typename... Args>
T<Args...>&& Create(Args&&... args)
{
  return std::move(T<Args...>(std::forward<Args>(args)...));
}


Только, ИМХО, зря ты ссылку возвращаешь — по-моему, в этом случае объект, связанный со ссылкой, может не дожить до инициализации внешнего объекта.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: [Предложение] Вывод типа шаблона класса из конструктора
От: rg45 СССР  
Дата: 13.11.12 16:17
Оценка:
Здравствуйте, rg45, Вы писали:

R>Только, ИМХО, зря ты ссылку возвращаешь — по-моему, в этом случае объект, связанный со ссылкой, может не дожить до инициализации внешнего объекта.


Да, так и есть, вот и подтверждение (gcc 4.7.2):

#include <iostream>
#include <utility>
 
template<template<typename...> class T, typename... Args>
T<Args...>&& Create(Args&&... args)
{

  return std::move(T<Args...>(std::forward<Args>(args)...));
}
 
template<typename T>
struct A
{
  explicit A(T&&) { std::cout << "Explicit constructor" << std::endl; }
  A(const A&) { std::cout << "Copy constructor" << std::endl; }
  A(A&&) { std::cout << "Move constructor" << std::endl; }
  ~A() { std::cout << "Destructor" << std::endl; }
};
 
int main()
{
  A<int> a = Create<A>(1);
}

Output:
Explicit constructor
Destructor
Move constructor
Destructor
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: [Предложение] Вывод типа шаблона класса из конструктора
От: _NN_ www.nemerleweb.com
Дата: 13.11.12 16:26
Оценка: -1
Здравствуйте, rg45, Вы писали:

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


R>>Только, ИМХО, зря ты ссылку возвращаешь — по-моему, в этом случае объект, связанный со ссылкой, может не дожить до инициализации внешнего объекта.


R>Да, так и есть, вот и подтверждение (gcc 4.7.2):


Ну вот, получается что нужно копировать.
А так бы объект создавался по месту без лишних движений.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: [Предложение] Вывод типа шаблона класса из конструктора
От: rg45 СССР  
Дата: 13.11.12 16:59
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Ну вот, получается что нужно копировать.

_NN>А так бы объект создавался по месту без лишних движений.

Ну, не все так грустно Попробуй подкорректировать тип результата функции — просто убери '&&' — пример останется компилируемым и вывод у него будет такой:

Explicit constructor
Move constructor
Destructor
Destructor


Как видишь, никакого копирования не добавилось, потому что в классе определен move constructor. И в большинстве случаев его не придется определять самостоятельно ибо:

12.8 Copying and moving class objects
9 If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator,
— X does not have a user-declared destructor, and
— the move constructor would not be implicitly defined as deleted.

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: [Предложение] Вывод типа шаблона класса из конструктора
От: flаt  
Дата: 13.11.12 17:02
Оценка:
Здравствуйте, _NN_, Вы писали:

R>>>Только, ИМХО, зря ты ссылку возвращаешь — по-моему, в этом случае объект, связанный со ссылкой, может не дожить до инициализации внешнего объекта.

_NN>Ну вот, получается что нужно копировать.
_NN>А так бы объект создавался по месту без лишних движений.
Нету там копирования, только инициализация и move.
Re: [Предложение] Вывод типа шаблона класса из конструктора
От: Кодт Россия  
Дата: 14.11.12 09:39
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Никто не знает планируется ли такая фишка в будущем ?


_NN>
_NN>template<typename T>
_NN>struct A
_NN>{
_NN>  A(T) {}
      // а если там внезапно ещё несколько конструкторов?
      A(T*) {}
      A(int) {}
_NN>};

_NN>A x(1); // Вывод T = int
_NN>



Конечно, автоматизировать создание конструирующих функций по мотивам шаблонных классов — это было бы приятно, но отсюда недалеко и до обратного вывода типов (когда по зависимому имени можно однозначно вывести параметры шаблона — почему бы компилятору не делать это?)
Даёшь Хиндли-Милнера ad hoc в массы C++1x! (troll mode off).
Перекуём баги на фичи!
Re[6]: [Предложение] Вывод типа шаблона класса из конструктора
От: Erop Россия  
Дата: 14.11.12 09:55
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Ну вот, получается что нужно копировать.

_NN>А так бы объект создавался по месту без лишних движений.

Получается, что не надо мешать RVO, излишне запутывая код
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: [Предложение] Вывод типа шаблона класса из конструктора
От: jazzer Россия Skype: enerjazzer
Дата: 14.11.12 10:19
Оценка: +1
Здравствуйте, _NN_, Вы писали:

_NN>Никто не знает планируется ли такая фишка в будущем ?


_NN>
_NN>template<typename T>
_NN>struct A
_NN>{
_NN>  A(T) {}
_NN>};

_NN>A x(1); // Вывод T = int
_NN>


_NN>Может в С++11 можно что-то сделать ?


Во-первых, у этого класса может быть еще с десяток конструкторов.
Во-вторых, у этого класса могут быть специализации (в т.ч. частичные) с совсем другими конструкторами.
Ты предлагаешь компилятору решить уравнение: "По типу аргумента найди тип, с которым можно было бы инстанцировать шаблон и все его частичные специализации, и заодно просмотри все его полные специализации, и найди из всей этой кучи те, у которых будет подходяший данному аргументу конструктор"?

Стандартный способ — однострочные функции типа make_ххх, например: make_pair, make_tuple, make_shared (уже в стандарте).
Так что следуй стандарту и будет тебе счастье.
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[7]: [Предложение] Вывод типа шаблона класса из конструктора
От: Vain Россия google.ru
Дата: 15.11.12 02:16
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ну, не все так грустно Попробуй подкорректировать тип результата функции — просто убери '&&' — пример останется компилируемым и вывод у него будет такой:

R>
R>Explicit constructor
R>Move constructor
R>Destructor
R>Destructor
R>

R>Как видишь, никакого копирования не добавилось
А чего деструктор два раза вызвался?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[8]: [Предложение] Вывод типа шаблона класса из конструктора
От: rg45 СССР  
Дата: 15.11.12 07:35
Оценка:
Здравствуйте, Vain, Вы писали:

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


R>>Ну, не все так грустно Попробуй подкорректировать тип результата функции — просто убери '&&' — пример останется компилируемым и вывод у него будет такой:

R>>
R>>Explicit constructor
R>>Move constructor
R>>Destructor
R>>Destructor
R>>

R>>Как видишь, никакого копирования не добавилось
V>А чего деструктор два раза вызвался?

Сколько конструкторов, столько и деструкторов. Потому, что было создано два объекта — один внутри функции, другой — снаружи. В исходном варианте
Автор: rg45
Дата: 13.11.12
создавались эти же объекты и отрабатывали эти же конструкторы и деструкторы, только в другой последовательности, вследствие чего первый объект умирал раньше времени.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[9]: [Предложение] Вывод типа шаблона класса из конструктора
От: Vain Россия google.ru
Дата: 15.11.12 10:26
Оценка: 8 (1) +1
Здравствуйте, rg45, Вы писали:

R>Сколько конструкторов, столько и деструкторов. Потому, что было создано два объекта — один внутри функции, другой — снаружи.

А в чём собственно смысл разрушать объект, который "уехал" в другое меcто? Что вообще тогда разрушается?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[10]: [Предложение] Вывод типа шаблона класса из конструктора
От: rg45 СССР  
Дата: 15.11.12 11:51
Оценка: +1
Здравствуйте, Vain, Вы писали:

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


R>>Сколько конструкторов, столько и деструкторов. Потому, что было создано два объекта — один внутри функции, другой — снаружи.

V>А в чём собственно смысл разрушать объект, который "уехал" в другое меcто? Что вообще тогда разрушается?

В этом что-то есть. Можно было бы считать move-конструктор равнозначным деструктору для оригинального объекта. Но сделали по-другому: время жизни оригинального объекта не заканчивается после "переезда". Ведь move семантика применима не только к временным объектам, наверное, посчитали, что будет не очень хорошо, если, например, std::move будет оставлять после себя "трупы" объектов.

Кроме того, не во всех случаях понятно как реализовать предлагаемый тобой подход разработчикам компиляторов. Например, такой фрагмент (псевдо-)кода:

void foo(T&); 

void bar()
{
  T t;
  foo(t);
}

Вопрос: должен ли компилятор генерировать вызов деструктора для объекта t? Ведь в результате вызова foo объект t вполне мог "переехать".
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Все проще! :)
От: rg45 СССР  
Дата: 15.11.12 12:16
Оценка: :)
Здравствуйте, _NN_, Вы писали:

R>>>Только, ИМХО, зря ты ссылку возвращаешь — по-моему, в этом случае объект, связанный со ссылкой, может не дожить до инициализации внешнего объекта.

R>>Да, так и есть, вот и подтверждение (gcc 4.7.2):
R>>
R>>template<template<typename...> class T, typename... Args>
R>>T<Args...>&& Create(Args&&... args)
R>>{
R>>  return std::move(T<Args...>(std::forward<Args>(args)...));
R>>}
R>>

_NN>Ну вот, получается что нужно копировать.
_NN>А так бы объект создавался по месту без лишних движений.


И как я сразу не обратил внимание, что std::move здесь не нужен. Эта функция нужна в тех случаях, когда у нас изначально есть lvalue-объект, который мы хотим превратить в rvalue. А в нашем случае мы уже изначально имеем rvalue. Поэтому, во-первых, код упрощается:

#include <iostream>
#include <utility>
 
template<template<typename...> class T, typename... Args>
T<Args...> Create(Args&&... args)
{

  return T<Args...>(std::forward<Args>(args)...);
}
 
template<typename T>
struct A
{
  explicit A(T&&) { std::cout << "Explicit constructor" << std::endl; }
  A(const A&) { std::cout << "Copy constructor" << std::endl; }
  A(A&&) { std::cout << "Move constructor" << std::endl; }
  ~A() { std::cout << "Destructor" << std::endl; }
};
 
int main()
{
  auto a = Create<A>(1);
}

А, во-вторых, оптимизатор делает свое дело: инлайнит функцию и выбрасывает ВСЕ промежуточные move- и copy- конструкторы копирования. Результат получаем такой, как-будто мы непосредственно сконструировали объект:
[/ccode]
Output:
Explicit constructor
Destructor
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: [Предложение] Вывод типа шаблона класса из конструктора
От: Vamp Россия  
Дата: 15.11.12 14:02
Оценка:
J>Во-первых, у этого класса может быть еще с десяток конструкторов.
Ну это, как раз, не проблема. Точно так же как функций make_xx может быть с десяток. Комплятор выберет ту единственную, которая побеждает все остальные, и посмотрит, достаточно ли ее для определения полного типа.

J>Во-вторых, у этого класса могут быть специализации (в т.ч. частичные) с совсем другими конструкторами.

Вот со специализациями, конечно, труднее. Теоретически, например, можно диагностировать ошибку, если есть хоть одна специализация — трактовать как ambiguity.

J>Стандартный способ — однострочные функции типа make_ххх, например: make_pair, make_tuple, make_shared (уже в стандарте).

J>Так что следуй стандарту и будет тебе счастье.
C однострочными функциями для того, чтобы с ними нормально работать, не обойтись без auto. То есть, какой там тип — программисту только гадать остается. И я не знаю, насколько хорошо синтаксический анализатор IDE способен такие конструкции парсить. В предложенном варианте можно, например, объявлять переменные так:
A<auto> a(1);

Уже хлеб.
Да здравствует мыло душистое и веревка пушистая.
Re[3]: [Предложение] Вывод типа шаблона класса из конструктора
От: Evgeny.Panasyuk Россия  
Дата: 15.11.12 14:12
Оценка:
Здравствуйте, _NN_, Вы писали:

E>>Ты расскажи чего тебе и для чего на самом деле надобно-то, а то может уже есть готовое?..

_NN>Скажем типичный пример:
_NN>
_NN>vector<int> v = {1,2,3};
_NN>sort(v.begin(), v.end(), less<int>());
_NN>

_NN>Вот тут хотелось бы получить вывод шаблонного типа.

А по какому аргументу ты собрался тип less'а выводить

Может тебе нужно что-то типа
struct PolymorphicLess
{
    template<typename T>
    bool operator()(const T &x,const T &y) const
    {
        return less<T>()(x,y);
    }
};
...
sort( v.begin(), v.end(), PolymorphicLess() );

?
Только вот согласно SGI (что в стандарте — надо смотреть..) тип третьего аргумента у sort должен иметь typedef'ы аргументов, сам sort конечно в них по-идеи не должен смотреть, но имеет право.
Но тебя же в общем не sort интересует?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.