Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
DiffEreD
1430 / 767 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
#1

Возвращаемый тип шаблона через std::common_type - C++

08.12.2012, 13:11. Просмотров 627. Ответов 11
Метки нет (Все метки)

Вот отрывок моего кода. Не могу понять как определить возвращаемый тип объекта matrix.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename V, typename U, size_t R, size_t C>
matrix</*U или V*/,R,C> operator+(const V& value, const matrix<U,R,C>& rhs)                     //!matrix+matrix
{
    std::cout<<"!matrix+matrix\n";
    std::cout<<"common_type<V,U>::type = "<<typeid(std::common_type<V,U>::type).name()<<std::endl;
    if (!std::is_fundamental<V>::value) throw std::logic_error ("Не совместимый тип при операции +\n");
    else
    {
        matrix<std::common_type<V,U>::type,R,C> ret_matrix(rhs);
        ret_matrix+=value;
        return ret_matrix;
    }
}
Такое не проходит:
C++
1
2
template<typename V, typename U, size_t R, size_t C>
matrix<std::common_type<V,U>::type,R,C> operator+(const V& value, const matrix<U,R,C>& rhs) {...}
Через auto тоже не проходит.
Как это правильно сделать?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.12.2012, 13:11
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Возвращаемый тип шаблона через std::common_type (C++):

Функции, возвращаемый тип - C++
Как сделать так, что бы функция возвращала разный тип данных, в зависимости от некой глобальной переменной? Например, если эта...

Возвращаемый тип по умолчанию - C++
Приветствую всех! В книге Р. Лафоре &quot;Объектно-ориентированное программирование в C++&quot; прочитал следующее: Скажите, с чем связан...

Непонятный возвращаемый тип - C++
Расскажите какой тип должен быть у переменной idRe, чтобы можно было бы присвоить ему значение s.length , если s объект класса string?

Перегрузка оператора - возвращаемый тип - C++
class A { private: int x; public: A&amp; operator += (int y); }; A&amp; A::operator += (int y) { x = y; ...

Перегруженные функции. Возвращаемый тип - C++
Добро всем времени суток. Изучаю Р.Лаворе книгу и наткнулся на непонятныий мне аспект. Вот есть код: String(char s) { ...

что за возвращаемый тип, и как работает функция? - C++
pair&lt;string, string&gt; splitExpression(string expr) { stringstream ss; ss &lt;&lt; expr; pair&lt;string, string&gt; result; getline(ss,...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
gray_fox
What a waste!
1520 / 1223 / 70
Регистрация: 21.04.2012
Сообщений: 2,560
Завершенные тесты: 3
08.12.2012, 13:32 #2
Цитата Сообщение от yuron_477 Посмотреть сообщение
std::common_type<V,U>::type
typename std::common_type<V,U>::type.
Это как минимум, т.к. type - зависимый от U и V тип.

Добавлено через 11 минут
Цитата Сообщение от yuron_477 Посмотреть сообщение
if (!std::is_fundamental<V>::value) throw std::logic_error ("Не совместимый тип при операции +\n");
Кстати, вместо
C++
1
if (!std::is_fundamental<V>::value) throw std::logic_error ("Не совместимый тип при операции +\n");
логичнее было бы
C++
1
static_assert(std::is_fundamental<V>::value, "Не совместимый тип при операции +.");
0
DiffEreD
1430 / 767 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.12.2012, 13:37  [ТС] #3
static_assert приму к сведению, а вот относительно typename std::common_type<V,U>::type чета я не понял, где его определять?
0
gray_fox
What a waste!
1520 / 1223 / 70
Регистрация: 21.04.2012
Сообщений: 2,560
Завершенные тесты: 3
08.12.2012, 13:51 #4
yuron_477, например здесь:
Цитата Сообщение от yuron_477 Посмотреть сообщение
matrix</*U или V*/,R,C>
C++
1
matrix<typename std::common_type<U, V>::type, R, C>
вообщем везде, где использушь std::common_type, и вообще с любыми типами, которые зависят от параметра шаблона, нужен typename. Компилятор не в курсе, что такое type - тип, статический метод или ещё что-нибудь, надо явно это указывать.
0
DiffEreD
1430 / 767 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.12.2012, 14:14  [ТС] #5
Да, все заработало. Вообщем, репект и уважуха
Окончательный вариант:
C++
1
2
3
4
5
6
7
8
9
10
template<typename V, typename U, size_t R, size_t C>
matrix<typename std::common_type<U, V>::type,R,C> operator+(const V& value, const matrix<U,R,C>& rhs)                       //!matrix+matrix
{
    //std::cout<<"!matrix+matrix\n";
    //std::cout<<"common_type<V,U>::type = "<<typeid(typename std::common_type<U, V>::type).name()<<std::endl;
    static_assert(std::is_fundamental<V>::value, "Не совместимый тип при операции +.");
    matrix<typename std::common_type<U, V>::type,R,C> ret_matrix(rhs);
    ret_matrix+=value;
    return ret_matrix;
}
Еще, походу, спрошу про static_assert - как его правильно обрабатывать при срабатывании?
0
gray_fox
What a waste!
1520 / 1223 / 70
Регистрация: 21.04.2012
Сообщений: 2,560
Завершенные тесты: 3
08.12.2012, 14:22 #6
Цитата Сообщение от yuron_477 Посмотреть сообщение
static_assert - как его правильно обрабатывать при срабатывании?
Всмысле? static_assert - это как assert, только времени компиляции. Если его первый параметр - false, то будет ошибка компиляции с сообщением из его второго параметра. Смысл в том, что std::is_fundamental<V>::value вычисляется на этапе компиляции, и помоему лучше ловить такие штуки во время компиляции вместо времени выполнения (например, бросать исключение, как в твоём примере).
0
DiffEreD
1430 / 767 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.12.2012, 14:37  [ТС] #7
Понял, уже разобрался.
0
zarko97
276 / 36 / 0
Регистрация: 11.10.2015
Сообщений: 381
25.12.2016, 19:02 #8
А не проще так было сделать:
C++
1
2
3
4
5
template<class V, class U, size_t R, size_t C>
matrix<typeof(V() + U()),R,C> operator+(const V& value, const matrix<U,R,C>& rhs)
{
     // бла бла бла...
}
0
GbaLog-
Любитель чаепитий
2772 / 1294 / 311
Регистрация: 24.08.2014
Сообщений: 4,589
Записей в блоге: 1
Завершенные тесты: 2
25.12.2016, 19:06 #9
Цитата Сообщение от zarko97 Посмотреть сообщение
А не проще так было сделать
Нет, потому что тогда код стал бы непереносимым, т.к. никакого typeof в языке с++ по стандарту нет.
0
Nick Alte
Эксперт С++
1637 / 1009 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
25.12.2016, 19:16 #10
Цитата Сообщение от zarko97 Посмотреть сообщение
А не проще так было сделать
Чисто теоретически, у типа V или U может не быть конструктора по умолчанию.
С другой стороны, не факт, что результат суммирования будет иметь тот же тип, что даст common_type (да, прокси-типы, это я про вас подумал!).
Получается, более корректным вариантом будет такой:
C++
1
matrix<decltype(std::declval<V>() + std::declval<U>()), R, C>
Впрочем, если мы имеем дело с прокси-типами, они и эту малину испортят.
0
zarko97
276 / 36 / 0
Регистрация: 11.10.2015
Сообщений: 381
25.12.2016, 21:38 #11
Очень даже неплохой вариант, наверное, самый рациональный...если с тайпофами мутить то можно как-то так:
C++
1
2
3
4
5
template<class V, class U, size_t R, size_t C>
operator+(const V& value, const matrix<U,R,C>& rhs) -> matrix<typeof(value + rhs),R,C> 
{
     // бла бла бла...
}
0
hoggy
Нарушитель
6588 / 2769 / 476
Регистрация: 15.11.2014
Сообщений: 6,118
Завершенные тесты: 1
25.12.2016, 22:32 #12
Цитата Сообщение от DiffEreD Посмотреть сообщение
template<typename V, typename U, size_t R, size_t C>
matrix<std::common_type<V,U>::type,R,C> operator+(const V& value, const matrix<U,R,C>& rhs) {...}
http://rextester.com/PIR37802

C++
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//========================================================================
//========================================================================
//========================================================================
 
    /* demangle names ot types */
 
#include <typeinfo>
#include <string>
 
#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
 
    #include <cxxabi.h>
    #include <memory>
    
    std::string demangle(const char* name) {
    
        int status = -1; 
        std::unique_ptr<char, void(*)(void*)> res {
            abi::__cxa_demangle(name, NULL, NULL, &status),
            std::free
        };
        return (status == 0) ? res.get() : name ;
    }
#else
 
    std::string demangle(const char* name) 
        { return name; }
 
#endif
 
template <class T> std::string type(const T& t) 
    { return demangle(typeid(t).name()); }
 
 
//========================================================================
//========================================================================
//========================================================================
 
#include <iostream>
 
template<class U, size_t R, size_t C>
struct matrix
{
    matrix(){}
    
    matrix(auto&& rsh)
        { std::cout << type(*this) << " was build!\n"; }
    
    matrix& operator+=(const auto& value) 
        { return *this; }
};
 
template<class V, class U>
    using common_t = 
        typename std::common_type<V,U>::type;
 
template<class V, class U, size_t R, size_t C>
    using matrix_t = 
        matrix< common_t<V,U>,R,C>;
 
 
template<class V, class U, size_t R, size_t C>
matrix_t<V,U,R,C> operator+(const V& value, const matrix<U,R,C>& rhs) 
{
    static_assert(
        std::is_fundamental<V>::value,
        "not compatible type for operator+"
    );
    
    std::cout <<"!matrix+matrix\n";
    
    std::cout << "common_type<V,U>::type = " 
        << type(common_t<V,U>{}) 
        << std::endl;
    
    matrix_t<V,U,R,C> ret_matrix(rhs);
    ret_matrix += value;
    return ret_matrix;
}
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    matrix<int, 10,20> matrixSample;
    auto result = 10.5 + matrixSample;
    
    std::cout << "type of result is " << type(result)<< std::endl;
    
}
Добавлено через 2 минуты
Цитата Сообщение от gray_fox Посмотреть сообщение
typename std::common_type<V,U>::type.
вместо этого можно использовать:
C++
1
common_type_t<V,U>
Добавлено через 15 секунд
Цитата Сообщение от gray_fox Посмотреть сообщение
typename std::common_type<V,U>::type.
вместо этого можно использовать:
C++
1
common_type_t<V,U>
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.12.2016, 22:32
Привет! Вот еще темы с ответами:

Возвращаемый тип конструктора копирования в абстрактном классе - C++
Здравствуйте! Есть абстрактный класс (с &quot;чистыми&quot; виртуальными функциями), и в нем необходимо явно определить конструктор копирования....

В наследнике(-ах) требуется изменить возвращаемый тип этих функций. - C++
Есть базовый класс. Есть наследник базового класса. В базовом классе есть два виртуальных метода - Get(int id) и Set(int id). В...

Какой символьный тип использует тип std::string? - C++
Какой тип данных использует класс String? Char? И написано ли это в в документе #include &lt;string&gt;?

Для чего нужен возвращаемый тип в перегрузке ввода >> и почему без него него выдаётся ошибка? - C++
Для чего нужен возвращаемый тип в перегрузке ввода &gt;&gt;, какую роль он выполняет что без него него выдаётся ошибка. cin объект istream...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
25.12.2016, 22:32
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru