Korzystam z biblioteki C ++ ( strf ), która gdzieś w niej zawiera następujący kod:
namespace strf {
template <typename ForwardIt>
inline auto range(ForwardIt begin, ForwardIt end) { /* ... */ }
template <typename Range, typename CharT>
inline auto range(const Range& range, const CharT* sep) { /* ... */ }
}
Teraz chcę użyć strf::range<const char*>(some_char_ptr, some_char_ptr + some_length)
w moim kodzie. Ale jeśli to zrobię, pojawia się następujący błąd (z NVCC CUDA 10.1):
error: more than one instance of overloaded function "strf::range" matches the argument list:
function template "auto strf::range(ForwardIt, ForwardIt)"
function template "auto strf::range(const Range &, const CharT *)"
argument types are: (util::constexpr_string::const_iterator, util::constexpr_string::const_iterator)
Biblioteka kod może być prawdopodobnie zmieniła tego uniknąć (np za pomocą:
inline auto range(const typename std::enable_if<not std::is_pointer<typename std::remove_cv<Range>::type>::value, Range &>::type range, const CharT* sep)
upewnić Range
się, że nie jest wskaźnikiem); ale nie mogę teraz wprowadzić tej zmiany. Zamiast tego chcę w jakiś sposób wskazać kompilatorowi, że naprawdę mam na myśli tylko jeden argument szablonu, nie jeden określony, a drugi wywnioskowany.
Czy mogę to zrobić?
Byłbym wdzięczny za odpowiedzi dla C ++ 11 i C ++ 14; Odpowiedzi w C ++ 17 dotyczące przewodników po dedukcji są mniej przydatne, ale jeśli masz, opublikuj je (dla przyszłych wersji NVCC ...)
Aktualizacja: sama biblioteka strf została zaktualizowana w celu obejścia tej sytuacji, ale pytanie jest zadane.
char*
ale czy to nie jest rozwiązanie?Odpowiedzi:
Następnie zadzwoń
range1
zamiaststrf::range
.range1_ptr<T>(...)
zawsze można użyć do jawnego wywołania szablonu, biorąc jeden argument szablonu, ale nie robi on żadnego odliczenia od argumentów.range1
replikuje odliczenie od oryginalnegostrf::range
szablonu.Działa to, ponieważ [temp.deduct.funcaddr] / 1 mówi, że dedukcja argumentu szablonu przy przyjmowaniu adresu funkcji bez typu docelowego konwersji jest wykonywana na każdym szablonie funkcji kandydującej, tak jakby listy parametrów i argumentów hipotetycznego wywołania były pusty. Zatem drugiego argumentu szablonu nie można wywnioskować dla drugiego przeciążenia dwoma parametrami szablonu. Pozostał tylko kandydat na pierwsze przeciążenie, które zostanie wybrane jako cel wskaźnika funkcji.
Dopóki nie istnieje drugi szablon funkcji kandydata, dla którego można utworzyć prawidłowy identyfikator szablonu z tylko jednym argumentem,
range1_ptr
zawsze można go użyć do wywołania szablonu funkcji przyjmującego jeden argument jednoznacznie. W przeciwnym razie utworzenie wystąpieniarange1_ptr
spowoduje błąd z powodu niejednoznaczności.źródło
strf::range<T>
?pretty_please_with_sugar_on_top()
? ... C ++ może być czasem tak dziwny ...Co powiesz na przejście przez
using
?źródło
range()
wersja jest kompatybilnatpf
; inny przypadek może być inny.tfp x = &strf::range<char const *>;
); w ten sposób przypuszczam, że masz ogólne rozwiązanie, prawie równoważne rozwiązaniu z orzecha włoskiegoRozwiązaniem jest
1) przede wszystkim należy podać typ drugiego argumentu, np
(char *)(some_char_ptr + some_length)
2) nie używaj
const
obu, działa to dobrze:Można spróbować wymienić
(char *)
się(const char *)
w lewo lub w prawo, to nadal działa.źródło
const
dane.