Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++
Войти
Регистрация
Восстановить пароль
 
hoggy
Заблокирован
Эксперт С++
#1

[c++][template][sfinae] перегрузки шаблонов

09.10.2017, 16:56. Просмотров 213. Ответов 2
Метки нет (Все метки)

добрый вечер.


сабж:

есть шаблон функции работы со строками.
если параметр возвращаемого значения явно не задан,
то шаблон должен вывести его из аргумента.

если задан - вернуть соответственно указанному.

при этом, если явно указан класс строки
(класс-строки - это класс, для которого определена функция-член c_str() )

тогда его и возвращаем.

в остальных случаях - дедукция типа символа,
и конструирование std::basic_string<символ>

таким образом,
в качестве явно-возвращаемого типа можно указать
либо класс строки, либо тип символа.

пример:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// возвращаемый тип: std::basic_string<char>
// явно не указан, поэтому выведен автоматически
const char* text1 = ""
example(text1); 
 
// возвращаемый тип: std::basic_string<wchar_t>
// явно не указан, поэтому выведен автоматически
const wchar_t* text2 = L""
example(text2); 
 
// возвращаемый тип: std::basic_string<char>
// явно указан тип символа, 
// на базе которого конструируется тип строки 
example<char>(""); 
 
// возвращаемый тип: std::string
// явно указан тип - строка (у типа обнаружен с_str)
// вот его и возвращаем
example<std::string>("");

сильно утрированный, но рабочий код модели:
http://rextester.com/KPUNYQ26509

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
#include <iostream>
 
#define dMYDETAIL detail
 
namespace detail{
   
    
    template<class s> 
    class check
    {
        using type = ::std::remove_cv_t<s>;
        
        enum { eISCHAR   
            = ::std::is_same<char, type>::value};
        
        enum { eISSTRING 
            = ::std::is_same<::std::string, type>::value };
    public:
        enum { value = eISCHAR || eISSTRING };
    };
 
    template<class s, bool> 
        struct retstring
    { using type = std::string; };
 
    template<class s> 
        struct retstring<s, false>;
    
}//namespace detail
 
template<class s, bool chk> 
using retstring 
    = typename dMYDETAIL::retstring<
        s, dMYDETAIL::check<s>::value == chk 
    >::type;
 
template<class s> 
using retgeneral 
    = retstring<s, false>;
 
template<class s> 
using retspecial 
    = retstring<s, true>;
 
template<class s>
retgeneral<s> foo(const s&) { 
    std::cout << "retgeneral\n";
    return retgeneral<s>{};
}
 
template<class ret, class s>
retspecial<ret> foo(const s&) 
{ 
    std::cout << "retspecial\n";
    return retspecial<ret>{};
}
 
int main()
{
    foo("");                      
    foo<char>("");                
    foo<const char>("");
    foo<std::string>("");
    foo<const std::string>("");
    
    std::string v;
    foo<const std::string>(v);
    foo<std::string>(v);
    foo<char>(v);
    foo<const char>(v);
    //foo<int>(v);
}
удобный дизайн.
казалось бы - то, что нужно.

но вылезла оказия:
если попытаться инстанцировать функцию с кривыми параметрами:

C++
1
foo<int>(v);
получаем ожидаемую ошибку компиляции:

Код
source_file.cpp: In function ‘int main()’:
source_file.cpp:72:15: error: 
no matching function for call to ‘foo(std::__cxx11::string&)’
     foo<int>(v);
               ^
source_file.cpp:47:15: note: 
candidate: template<class s> retgeneral<s> foo(const s&)
 retgeneral<s> foo(const s&) { 
               ^
source_file.cpp:47:15: note:   
template argument deduction/substitution failed:
source_file.cpp:72:15: note:  
cannot convert ‘v’ (type ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’) to type ‘const int&’
     foo<int>(v);
               ^
source_file.cpp:53:17: note: 
candidate: template<class ret, class s> retspecial<ret> foo(const s&)
 retspecial<ret> foo(const s&) 
                 ^
source_file.cpp:53:17: note:   
template argument deduction/substitution failed:
собственно так это все и должно работать.

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

и что бы сильно не думалось,
хочется обыграть "инвалидный кейс".
влепить туда читабельный статик_ассерт.

таким образом,
если вбить некорректные параметры:
C++
1
foo<int>(v);
нужно, что бы каким то образом сработала третья перегрузка.
ну или как либо ещё привести в действие static_assert,
с понятным и красивым сообщением,
на чистом английском.

вопрос: это вообще возможно?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.10.2017, 16:56
Ответы с готовыми решениями:

SFINAE не работает
Почему conversion operator не хочет работать ни так #include &lt;iostream&gt; #include &lt;type_traits&gt; ...

[SFINAE] GCC/Clang - success. CL - failed
добрый вечер. следующий код успешно собирают gcc/clang но не может собрать cl (компилятор...

SFINAE перегрузка по сигнатуре Callable объекта
Всем привет Есть вот у меня функция, принимающая на вход произвольный Callable-объект:...

Intrusive list template
intrusive list template для тренировки хочу попробовать написать шаблон списка, который...

Своеобразное раскрытие аргументов variadic template
Товарищи. Как бы сделать так, чтобы variadic раскрылся в нечто такое: template &lt;typename ......

2
notAll
450 / 171 / 62
Регистрация: 27.05.2016
Сообщений: 453
Завершенные тесты: 2
09.10.2017, 22:05 #2
А если в retstring запихнуть?
C++
1
2
3
4
5
6
7
8
9
10
11
    template <class s, bool>
    struct retstring
    {
        using type = std::string;
    };
 
    template <class s>
    struct retstring<s, false>
    {
        static_assert(dMYDETAIL::check<s>::value == true, "s must be c_str() compatible");
    };
0
hoggy
Заблокирован
Эксперт С++
09.10.2017, 22:25  [ТС] #3
Цитата Сообщение от notAll Посмотреть сообщение
А если в retstring запихнуть?
представленная модель не работает.
от слова совсем.

нужна другая.

я уже придумал как сделать.
осталось только сделать.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.10.2017, 22:25

[template] почему код не компилируется без конструктора
добрый вечер. вопрос поместил прямо в коде. http://rextester.com/AESO94403 #include...

[c++][bug][template][cross - platform] workaround for msvc`s compiler
добрый день. следующий код успешно собирается gcc http://rextester.com/OIRJ27111 #include...

Перенаправление указателя при перегрузке оператора в variadic template
Есть вот такой вот код (сделан в vs2014): #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include...


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

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

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