Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.65/40: Рейтинг темы: голосов - 40, средняя оценка - 4.65
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615

Call of overloaded template function is ambiguous

22.12.2016, 22:31. Показов 7681. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер.
Есть два метода:
C++
1
2
3
4
5
6
7
8
9
10
11
template<typename T, uint8_t count, bool msb = true, bool wait = true, typename U1, typename U2>
static T read(U1 address, U2 data)
{
    //..
}
 
template<typename T, bool msb = true, bool wait = true, typename U1, typename U2>
static T read(U1 address, U2 data)
{
    return Complex::read<T, sizeof(T), msb, wait>(address, data);
}
При записи:
C++
1
int32_t result = Spi::Io::Complex::template read<int32_t, 3U>(0x01, 0xCC);
пишет:
Code
1
call of overloaded template function is ambiguous.
В качестве кандидатов предлагает эти мои две метода.
Я не понял, что ему не ясно? Второй параметр шаблона - число (а не булево значение). Значит все должно определяться однозначно.

Удалить второй метод и записать первый с uint8_t count = sizeof(T) не очень хотелось бы.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
22.12.2016, 22:31
Ответы с готовыми решениями:

Ambiguous call to overloaded function
При использовании sqrt (да и других мат. функций(sin, cos, pow...) ) выдает ошибку, где говорится о неоднозначности. Скажем: ...

Error: call of overloaded ‘Function’ is ambiguous
log.cpp:166:25: error: call of overloaded ‘localtime_r(time_t*, tm*)’ is ambiguous log.cpp:166:25: note: candidates are: ...

'sqrt' : ambiguous call to overloaded function
здраствуйте! ошибка в заголовке. Чё то я запамятовал как указать компилятору какую именно версию функции использовать, думал так int...

14
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
22.12.2016, 22:33
[progeR], разве "по умолчанию" может быть не в конце?
0
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
22.12.2016, 22:41  [ТС]
C++
1
int32_t result = Spi::Io::Complex::template read<int32_t>(0x01, 0xCC);
Так работает. Получается может.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
22.12.2016, 22:55
[progeR], я тихо спросил?
0
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
23.12.2016, 04:02
работает, правда не знаю как грамотно в forward эти auto&& засунуть при передаче во второй функции:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<uint8_t count, typename T, bool msb = true, bool wait = true>
static T read(auto&& address, auto&& data)
{
    /*код*/
    return T();
}
 
template<typename T, bool msb = true, bool wait = true>
static T read(auto&& address, auto&& data)
{
    return read<sizeof(T), T, msb, wait>(address, data);
}
 
int main() {
int32_t result = read<3U, int32_t, false, false>(0x01, 0xCC);
        int32_t result1 = read<int32_t, true, false>(0x01, 0xCC);
}
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.12.2016, 12:00
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
разве "по умолчанию" может быть не в конце?
это не код, это шандец какой то.
смотрите: тип параметров выводятся автоматически
из аргументов с которыми была запущена функция.

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

косяк же приключился потому,
что значение интегральной константы 3U может кастиццо и в int8_t, и в bool.
компилятор как бы не телепат, во что именно предполагается каст.

фишка в том, что даже если бы каста не было,
всё равно компилятор бы затупил:
http://rextester.com/PHRU21941

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
#include <iostream>
#include <string>
 
template<typename T, uint8_t count, bool msb = true, bool wait = true, typename U1, typename U2>
void test(U1 address, U2 data)
{
    std::cout <<"uint8_t!\n";
}
 
template<typename T, bool msb = true, bool wait = true, typename U1, typename U2>
void test(U1 address, U2 data)
{
    std::cout <<"bool!\n";
}
 
template<typename T, int count>
void test2()
{
    std::cout <<"uint8_t!\n";
}
 
template<typename T, bool msb>
void test2()
{
    std::cout <<"bool!\n";
}
 
 
int main() 
{
    //WTF ????
    test<int32_t, 3, true, int, int>(0x01, 0xCC);
    test<int32_t, true, true, int, int>(0x01, 0xCC);
    
    // error: call of overloaded ‘test2()’ is ambiguous
    //test2<int32_t, 1   >();
    //test2<int32_t, true>();
}
я не могу сказать точно, почему так.
почему компиляется первый test (причем через жёпь),
и не работает второй

кастую DrOffset в тред
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,178
23.12.2016, 12:45
Лучший ответ Сообщение было отмечено hoggy как решение

Решение

Цитата Сообщение от [progeR] Посмотреть сообщение
Я не понял, что ему не ясно? Второй параметр шаблона - число (а не булево значение). Значит все должно определяться однозначно.
В С++ выбор лучшей функции-кандидата в процессе overload resolution выполняется только на основе того, как хорошо типы аргументов функции соответствуют типам параметров функции.

Насколько же хорошо типы нетиповых (non-type) аргументов шаблона соответствуют типам нетиповых параметров шаблона значения не имеет и никогда не имело. И на overload resolution это никакого влияния не оказывает. В С++ нет механизма "предпочтения" тех или иных версий перегруженного шаблона на основе того, как "хорошо" совпадали типы шаблонных аргументов. Компилятор интересует лишь то, является ли аргумент допустимым для данного параметра.

Все, что компилятор должен сделать - это нагенерировать из ваших шаблонов набор функций-кандидатов, к которым потом будет применяться overload resolution. Все что для этого надо - это чтобы шаблон функции успешно специализировался. Если нетиповой параметр шаблона является целочисленным значением, то любой целочисленный аргумент, который не требует сужающего преобразования (narrowing conversion) является допустимым аргументом шаблона. Так как преобразование unsigned -> bool формально не является сужающим, ваш второй шаблон тоже успешно включается в рассмотрение.

Я бы даже сказал, что существует больше риска того, что ваш первый шаблон будет исключен из рассмотрения, ибо преобразование unsigned -> uint8_t в общем случае может быть сужающим. Но для явной константы 3U сужения нет, поэтому первый шаблон был допущен к рассмотрению.

---

Но это еще пол-дела. Даже если бы в С++ существовал некий механизм мета-overload resolution, рассматривающий на нетиповые параметрах шаблонов, у вас бы все равно сохранилась неоднозначность. Точного соответствия-то у вас нет. Для первого шаблона требуется преобразование unsigned -> uint8_t, а для второго unsigned -> bool. Эти преобразования обладают одинаковым рангом и приводят к неоднозначности, как в таком простом примере

C++
1
2
3
4
5
6
void foo(uint8_t) {}
void foo(bool) {}
 
int main() {
    foo(3U); // ERROR: ambiguous
}
2
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.12.2016, 12:55
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Так как преобразование unsigned -> bool формально не является сужающим
sizeof(bool) - 1.
sizeof(uint8_t) - 1
тут в обоих случаях получается сужающий каст.
почему был выбран bool ?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,178
23.12.2016, 13:14
Лучший ответ Сообщение было отмечено hoggy как решение

Решение

Цитата Сообщение от hoggy Посмотреть сообщение
почему компиляется первый test
Не понимаю, что тут может быть непонятного.

Первый шаблон даже отдаленно не подходит, ибо типовой аргумент int никак не может быть передан через нетиповой параметр bool wait. Остается только второй шаблон. Все.

Поправка:

Тут я не прав. Первый вызов не должен компилироваться из-за сужающей конверсиии (см. ниже).


Цитата Сообщение от hoggy Посмотреть сообщение
(причем через жёпь),
??? (Недоумение)

Добавлено через 12 минут
Цитата Сообщение от hoggy Посмотреть сообщение
sizeof(bool) - 1.
sizeof(uint8_t) - 1
тут в обоих случаях получается сужающий каст.
почему был выбран bool ?
Тут ситуация интересная. Конверсия unsigned -> bool действительно является сужающей. Допускание
такой конверсии в разных контекстах - баги в GCC и clang

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57891
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65043
https://llvm.org/bugs/show_bug.cgi?id=22566#c1

В clang, пишут, исправили (не знаю, везде ли).

Что же касается преобразования unsigned -> uint8_t, то оно формально не является сужающим, если исходное значение - константа, помещающаяся в uint8_t.

То есть в случае ТС действительно имеет место безобразие с некоторыми компиляторами, допускающими сужающую конверсию в тех контекстах, когда она запрещена.
2
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.12.2016, 13:22
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Первый шаблон даже отдаленно не подходит, ибо типовой аргумент int никак не может быть передан через нетиповой параметр bool wait.
ничего не понял.
uint8_t - это unsigned char по мнению одного из gcc
у него такой же размер, как у буля.
test<int32_t, 3,
цыферка 3 - обычный int. её придется кастить либо у 1 байтовому булю, либо к 1 байтовому чару.
в обоих случаях размер сжимается.
почему именно буль?

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
??? (Недоумение)
говнокод - такой говнокод.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В чем затруднение?
уже ни в чем.
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Насколько же хорошо типы нетиповых (non-type) аргументов шаблона соответствуют типам нетиповых параметров шаблона значения не имеет и никогда не имело.
это разъясняет ситуацию со вторым тестом. мерси.
но никак не объясняет ситуацию с первым тестом.

Добавлено через 6 минут
прочел дополнение.
теперь все понятно.
спасибо))
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,178
23.12.2016, 13:24
Цитата Сообщение от hoggy Посмотреть сообщение
ничего не понял.
Еще раз, посмотрите внимательнее на первый шаблон. У него параметры <typename, uint8_t, bool, bool, typename, typename>, то есть <тип, значение, значение, значение, тип, тип>

Вы же в ваших вызовах

C++
1
2
test<int32_t, 3, true, int, int>(0x01, 0xCC);
test<int32_t, true, true, int, int>(0x01, 0xCC);
явно передаете <тип, значение, значение, тип, тип>

Это никак не может подойти к первому шаблону. Поэтому первый шаблон в ваших вызовах вообще отбрасывается сразу и более не рассматривается. Рассматривается только второй шаблон. У него параметры <typename, bool, bool, typename, typename>.

При этом первый вызов формально неверен из-за сужающего преобразования значения 3 к типу bool, но из-за бага в компиляторе он проходит. А во втором вызове проблем нет.
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.12.2016, 13:32
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Вы же в ваших вызовах
ааа! блин! точно))
надо же было так облажаццо))
мерси)
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,178
23.12.2016, 13:44
Код ТС:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstdint>
 
template<typename T, uint8_t count, bool msb = true, bool wait = true, typename U1, typename U2>
static T read(U1 address, U2 data)
{
  return 0;
}
 
template<typename T, bool msb = true, bool wait = true, typename U1, typename U2>
static T read(U1 address, U2 data)
{
  return 0;
}
 
int main()
{
  int32_t result = read<int32_t, 3U>(0x01, 0xCC);
}
Clang, в котором этот баг исправлен, спокойно компилирует

http://coliru.stacked-crooked.... 2c62493b19

А GCC до сих пор глючит

http://coliru.stacked-crooked.... 41e25acd46

Добавлено через 5 минут
Visual Studio 2015 в ответ на код

C++
1
2
3
int main() {
  bool b{3};
}
выдает предупреждение о сужающем преобразовании, то есть формально удовлетворяет требованию о необходимости диагностического сообщения. Но ситуацию с кодом ТС в Visual Studio 2015 это не спасает, ибо это "просто предупреждение".
3
23.12.2016, 15:59

Не по теме:

Цитата Сообщение от tapochka Посмотреть сообщение
не знаю как грамотно в forward эти auto&& засунуть при передаче
Думаю что так:
C++
1
return read<sizeof(T), T, msb, wait>(std::forward<decltype(address)>(address), std::forward<decltype(data)>(data));

0
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
23.12.2016, 22:22

Не по теме:

notAll, все-таки вроде так:

C++
1
return read<sizeof(T), T, msb, wait>(std::forward<std::decay_t<decltype(address)>>(address), std::forward<std::decay_t<decltype(data)>>(data));



Добавлено через 7 минут

Не по теме:

хотя не, с константами проблема

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.12.2016, 22:22
Помогаю со студенческими работами здесь

Ambiguous call to overloaded function / рекурсивная функция
Функция должна вызываться из движка на удаление связных списков. dellTree(Aster::tree); Далее она сама себя должна шерстать. void...

Ошибка: ('sqrt' : ambiguous call to overloaded function)
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;math.h&gt; using namespace std; int main() { setlocale(LC_ALL,...

Error C2668: 'sqrt' : ambiguous call to overloaded function
Собственно задание: треугольник задан координатами своих вершин. Найти его периметр и площадь Вот Код,но он почему не работате выдает...

Ambiguous access to overloaded function
Zdravstvuite,mogli li bi vi mne ob'qsnit' pochemy ne realiziruetsq kompilqtorom?Ponimaiu chto eto primitivno i v real'nosti v podobnoi...

Abiguous call to overloaded function
Рисую в opengl вентилятор Это - фрагмент кода, который рисует лопасть вентилятора. Тут обнаруживается 17 ошибок, в тех местах, где есть...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru