Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Определение по типу переменной, в которую возвращается значение / 17 сообщений из 17, страница 1 из 1
24.04.2017, 09:20
    #39443050
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
Есть такая примерная иерархия классов:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
class A
{
	typeA a_;
};

class B
{
	typeB a_;
};

class C
{
	typeC a_;
};


Можно ли как-то написать функцию Get, чтобы можно было вызывать так:
Код: plaintext
1.
2.
3.
4.
C c;
typeA a = c.Get(); // returns A::a_;
typeB b = c.Get(); // returns B::a_;
typeC c = c.Get(); // returns C::a_;


?

У меня получилось максимум сделать функцию-шаблон, куда передаётся тип класса (A,B,C) и из него возвращается соответствующая переменная. Но в общем случае мы не видим связь между именем класса и типом переменной. Наверно, можно попробовать сделать иерархию на основе шаблона класса, куда передавать тип (typeA, typeB, typeC), но не совсем понятно, как.
...
Рейтинг: 0 / 0
24.04.2017, 10:07
    #39443081
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
#include <iostream>
typedef int typeA;
typedef struct { int a, b; } typeB;


template <typename T> class A 
{
public:
	T a_;
	virtual T Get() = 0;
};

class realA : A<typeA>
{
public:
    realA() { a_ = 777; }
	typeA Get(){ return a_; }
};

class realB : A<typeB>
{
public:
    realB() { a_.a = 888; }
	typeB Get(){ return a_; }
};

int main()
{
	realA x;
	realB y;
	auto test = x.Get();
	auto test2 = y.Get();
	std::cout << test << std::endl;
	std::cout << test2.a << std::endl;
}
...
Рейтинг: 0 / 0
24.04.2017, 10:48
    #39443111
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMbЕсть такая примерная иерархия классов:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
class A
{
	typeA a_;
};

class B
{
	typeB a_;
};

class C
{
	typeC a_;
};


Можно ли как-то написать функцию Get, чтобы можно было вызывать так:
Код: plaintext
1.
2.
3.
4.
C c;
typeA a = c.Get(); // returns A::a_;
typeB b = c.Get(); // returns B::a_;
typeC c = c.Get(); // returns C::a_;


?

У меня получилось максимум сделать функцию-шаблон, куда передаётся тип класса (A,B,C) и из него возвращается соответствующая переменная. Но в общем случае мы не видим связь между именем класса и типом переменной. Наверно, можно попробовать сделать иерархию на основе шаблона класса, куда передавать тип (typeA, typeB, typeC), но не совсем понятно, как.


Обычный статический метод тебе тут подойдёт.
Правда, код будет малополезен. Он будет малополезен в любом случае, везде тебе нужно будет явно в вызове указывать статический тип класса, которого ты хочешь узнать "тип". Динамический тип у тебя везде тут C, и статический тип переменной -- С.

Ещё вариант -- простая невиртуальная функция с явным приведением типа при вызове или явным указанием скоупа класса при вызове. Эффект будет тот же -- тип придётся указывать, и толку в том, что ты вызовешь ещё функцию -- ноль.
...
Рейтинг: 0 / 0
24.04.2017, 10:50
    #39443113
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMbУ меня получилось максимум сделать функцию-шаблон, куда передаётся тип класса (A,B,C) и из него возвращается соответствующая переменная. Но в общем случае мы не видим связь между именем класса и типом переменной. Наверно, можно попробовать сделать иерархию на основе шаблона класса, куда передавать тип (typeA, typeB, typeC), но не совсем понятно, как.

Не понятно вообще, что ты тут хочешь.

Получить тип класса, тип которого ты уже и так знаешь ?
...
Рейтинг: 0 / 0
24.04.2017, 11:12
    #39443125
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
SiemarglНе, это не то
MasterZivПолучить тип класса, тип которого ты уже и так знаешь ?да, но сделать менее перегруженный код. Т.е, как я уже писал, работает в таком виде:
Код: plaintext
1.
2.
3.
4.
C c;
typeA a = c.Get<typeA>(); // returns A::a_;
typeB b = c.Get<typeB>(); // returns B::a_;
typeC c1 = c.Get<typeC>(); // returns C::a_;

но приходится 2 раза указывать класс.
можно, наверно, сверху обернуть шаблоном, который будет 2 раза этот тип указывать, чтобы наружу ничего не торчало.
можно (точно) делать фунцию Get и параметром передавать туда переменную требуемого типа. Но тогда придётся в одну строку писать декларацию, во вторую вызов Get. И я не смогу возвращать ссылки, а хотелось бы.

И кроме того, я ж могу ошибиться и написать:
Код: plaintext
1.
2.
3.
4.
C c;
typeA a = c.Get<typeC>(); // 
typeB b = c.Get<typeA>(); // 
typeC c1 = c.Get<typeB>(); // 

и если есть касты между типами, я это так и не замечу при компиляции
...
Рейтинг: 0 / 0
24.04.2017, 11:26
    #39443133
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMb,

Код: plaintext
1.
auto a = c.Get<typeA>();
...
Рейтинг: 0 / 0
24.04.2017, 11:36
    #39443140
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
Anatoly Moskovsky
Код: plaintext
1.
auto a = c.Get<typeA>();

Шах и мат
Даже нечего возразить
...
Рейтинг: 0 / 0
24.04.2017, 12:17
    #39443165
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMbДаже нечего возразить
А ты усложни задачу, введя указатели. Слабо написать так:
Код: sql
1.
std::unique_ptr<auto> a(c.Get<TypeA>());


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
24.04.2017, 12:33
    #39443183
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
Dimitry SibiryakovА ты усложни задачуя ещё толком на шаблонах первый вариант не написал, и у меня цель не усложнять, а упрощать :)
Проблема с шаблонами в том, что при вызове мы совсем не знаем, из какого типа нам звать функцию Get.
...
Рейтинг: 0 / 0
24.04.2017, 13:44
    #39443274
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
Проблема вот в чём. Мы хотим иметь более общий вариант описания объекта, чтобы не заводить кучу иерархий классов на каждую цепочку. Т.е. чтобы объявлять так:
Код: plaintext
1.
D<int, vector<float>, string> d;

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

я надеваю свой шаблонный плащ и шаблонную шляпу...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
template <typename... TS> class D{};
template <typename T1, typename... TS> class D<T1>: public <TS...>
{
	T1 a_;
protected:
	T1& _Get() {return a_;}
public:
	template <typename T> decltype(T::a_)& Get() {return T::_Get();}
};



всё ок, но тип мы определить не можем тут:
Код: plaintext
1.
2.
3.
D <int, string> d;
auto a = d.Get<string>();
auto b = d.Get<int>();// тут



Потому что у нас нету типа D<int> в иерархии, только D<string> и D<int, string> и извлечь из второго правильный тип для переменной a_ не получится (я сделал variadic template и для функции и несколько раз уронил компилятор,... но на вид это решило бы проблему совместимости типов, хотя и криво)

Решение проблемы весьма изящно!
Заводим ещё один шаблон, который будет нести информацию, а изначальный оставляем в качестве интерфейса:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
template <typename... TS> class D {};
template <typename T> class DS
{
	T a_;
protected:
	T& _Get() { return a_; }
};
template <typename T1, typename... TS> class D<T1, TS...>: public DS<T1>, public D<TS...>
{
public:
	template<typename T> decltype(DS<T>::a_)& Get() { return DS<T>::_Get(); }
};
...
Рейтинг: 0 / 0
24.04.2017, 14:48
    #39443329
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMb,

Это называется изящно???

Перегрузка по возвращаемому значению не зря же запрещена.

Может надо было по старинке?
Код: plaintext
1.
void Get(TypeA &retval)
...
Рейтинг: 0 / 0
24.04.2017, 15:32
    #39443374
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMb,

Еще возможна такая конструкция.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
struct A {};
struct B {};

struct S {
    template <typename T> operator T()
    {
        return T();
    }
};


int main()
{
    S s;
    A a = s;
    B b = s;

    return 0;
}
...
Рейтинг: 0 / 0
24.04.2017, 15:42
    #39443389
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
На всякий уточняю что я имел в виду, что ваш метод get() должен возвращать S, который умеет приводиться к нужному типу.
...
Рейтинг: 0 / 0
25.04.2017, 05:14
    #39443760
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
SiemarglЭто называется изящно???Ну да, довольно сложная конструкция, записанная в пять строчек. В чём и прелесть новых плюсов.
Давайте разберёмся, что не так в этой конструкции?SiemarglПерегрузка по возвращаемому значению не зря же запрещена.А, кстати, почему? Сидел, вспоминал, так и не вспомнил причину.
SiemarglМожет надо было по старинке?Да, можно и так, но я выше про это писал, тут есть 2 неудобства: запись в две строчки(decl + get), невозможность вернуть ссылку.Anatoly Moskovskyметод get() должен возвращать S, который умеет приводиться к нужному типунемного не совсем то. Т.е. как я понял, внутри S должны быть какие-то данные, в моём случае любые, int, vector<float>, string и потом как-то через operator T() должны кастоваться в T. Вот момент каста мне неясен. И у меня задумка другая: чёткая типизация. В 4-м посте я писал, что как раз стараюсь избежать любых кастов, чтобы автоматически избежать любых неявных ошибок.
...
Рейтинг: 0 / 0
25.04.2017, 09:02
    #39443819
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMb
Код: plaintext
1.
D<int, vector<float>, string> d;

И странно, что никто не сказал: "так это же tuple!" :)
Да, но хотелось пойти немного дальше, использовать типы-параметры как типы для векторов(а не просто переменных), а так же сделать методы для работы с этими векторами напрямую, не извлекая вектор из класса, что с tuple невозможно.
...
Рейтинг: 0 / 0
25.04.2017, 09:26
    #39443839
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
CEMbнемного не совсем то. Т.е. как я понял, внутри S должны быть какие-то данные
Нет. Там нужна всего лишь ссылка на c.
А дальше вы сами писали что у вас
CEMbработает в таком виде:
Код: plaintext
1.
2.
3.
4.
C c;
typeA a = c.Get<typeA>(); // returns A::a_;
typeB b = c.Get<typeB>(); // returns B::a_;
typeC c1 = c.Get<typeC>(); // returns C::a_;


но приходится 2 раза указывать класс.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
struct A {};
struct B {};

struct C {
   S get()
   {
        return S(*this);
   }
   template <typename T> T Get();  // это уже есть
};

struct S {
    C& c;
    S(C& c): c(c) {}
    template <typename T> operator T()
    {
        return c.Get<T>();
    }
};

int main()
{
    C c;
    A a = c.get();
    B b = c.get();

    return 0;
}
...
Рейтинг: 0 / 0
28.04.2017, 05:55
    #39445808
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определение по типу переменной, в которую возвращается значение
Anatoly Moskovsky, ага, работает. Даже можно в C сразу operator T() вставить.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Определение по типу переменной, в которую возвращается значение / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]