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

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

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

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

08.12.2012, 13:11. Просмотров 557. Ответов 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 тоже не проходит.
Как это правильно сделать?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.12.2012, 13:11     Возвращаемый тип шаблона через std::common_type
Посмотрите здесь:

Перегрузка оператора - возвращаемый тип C++
C++ Функции, возвращаемый тип
C++ C++11,mingw 4.7.2 Мьютекс не тип из std
В наследнике(-ах) требуется изменить возвращаемый тип этих функций. C++
C++ Перегруженные функции. Возвращаемый тип
C++ Возвращаемый тип конструктора копирования в абстрактном классе
Выбор значения для шаблона, bool отделить от std::is_integral C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
gray_fox
What a waste!
 Аватар для gray_fox
1249 / 1132 / 54
Регистрация: 21.04.2012
Сообщений: 2,357
Завершенные тесты: 3
08.12.2012, 13:32     Возвращаемый тип шаблона через std::common_type #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, "Не совместимый тип при операции +.");
DiffEreD
 Аватар для DiffEreD
1425 / 762 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.12.2012, 13:37  [ТС]     Возвращаемый тип шаблона через std::common_type #3
static_assert приму к сведению, а вот относительно typename std::common_type<V,U>::type чета я не понял, где его определять?
gray_fox
What a waste!
 Аватар для gray_fox
1249 / 1132 / 54
Регистрация: 21.04.2012
Сообщений: 2,357
Завершенные тесты: 3
08.12.2012, 13:51     Возвращаемый тип шаблона через std::common_type #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 - тип, статический метод или ещё что-нибудь, надо явно это указывать.
DiffEreD
 Аватар для DiffEreD
1425 / 762 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.12.2012, 14:14  [ТС]     Возвращаемый тип шаблона через std::common_type #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 - как его правильно обрабатывать при срабатывании?
gray_fox
What a waste!
 Аватар для gray_fox
1249 / 1132 / 54
Регистрация: 21.04.2012
Сообщений: 2,357
Завершенные тесты: 3
08.12.2012, 14:22     Возвращаемый тип шаблона через std::common_type #6
Цитата Сообщение от yuron_477 Посмотреть сообщение
static_assert - как его правильно обрабатывать при срабатывании?
Всмысле? static_assert - это как assert, только времени компиляции. Если его первый параметр - false, то будет ошибка компиляции с сообщением из его второго параметра. Смысл в том, что std::is_fundamental<V>::value вычисляется на этапе компиляции, и помоему лучше ловить такие штуки во время компиляции вместо времени выполнения (например, бросать исключение, как в твоём примере).
DiffEreD
 Аватар для DiffEreD
1425 / 762 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
08.12.2012, 14:37  [ТС]     Возвращаемый тип шаблона через std::common_type #7
Понял, уже разобрался.
zarko97
229 / 10 / 0
Регистрация: 11.10.2015
Сообщений: 51
25.12.2016, 19:02     Возвращаемый тип шаблона через std::common_type #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)
{
     // бла бла бла...
}
GbaLog-
Не Эксперт C++
2031 / 831 / 220
Регистрация: 24.08.2014
Сообщений: 3,188
Записей в блоге: 1
Завершенные тесты: 2
25.12.2016, 19:06     Возвращаемый тип шаблона через std::common_type #9
Цитата Сообщение от zarko97 Посмотреть сообщение
А не проще так было сделать
Нет, потому что тогда код стал бы непереносимым, т.к. никакого typeof в языке с++ по стандарту нет.
Nick Alte
Эксперт С++
1599 / 991 / 117
Регистрация: 27.09.2009
Сообщений: 1,910
Завершенные тесты: 1
25.12.2016, 19:16     Возвращаемый тип шаблона через std::common_type #10
Цитата Сообщение от zarko97 Посмотреть сообщение
А не проще так было сделать
Чисто теоретически, у типа V или U может не быть конструктора по умолчанию.
С другой стороны, не факт, что результат суммирования будет иметь тот же тип, что даст common_type (да, прокси-типы, это я про вас подумал!).
Получается, более корректным вариантом будет такой:
C++
1
matrix<decltype(std::declval<V>() + std::declval<U>()), R, C>
Впрочем, если мы имеем дело с прокси-типами, они и эту малину испортят.
zarko97
229 / 10 / 0
Регистрация: 11.10.2015
Сообщений: 51
25.12.2016, 21:38     Возвращаемый тип шаблона через std::common_type #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> 
{
     // бла бла бла...
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.12.2016, 22:32     Возвращаемый тип шаблона через std::common_type
Еще ссылки по теме:

Для чего нужен возвращаемый тип в перегрузке ввода >> и почему без него него выдаётся ошибка? C++
что за возвращаемый тип, и как работает функция? C++
C++ Возвращаемый тип по умолчанию
Какой символьный тип использует тип std::string? C++
Непонятный возвращаемый тип C++

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

Или воспользуйтесь поиском по форуму:
hoggy
5715 / 2306 / 417
Регистрация: 15.11.2014
Сообщений: 5,150
Завершенные тесты: 1
25.12.2016, 22:32     Возвращаемый тип шаблона через std::common_type #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>
Yandex
Объявления
25.12.2016, 22:32     Возвращаемый тип шаблона через std::common_type
Ответ Создать тему
Опции темы

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