ein*_*ica 27 c++ nvcc overload-resolution c++11 template-argument-deduction
我正在使用 C++ 库 ( strf ),其中的某处具有以下代码:
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) { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
现在,我想strf::range<const char*>(some_char_ptr, some_char_ptr + some_length)在我的代码中使用。但是如果我这样做,我会收到以下错误(使用 CUDA 10.1 的 NVCC):
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)
Run Code Online (Sandbox Code Playgroud)
该库的代码也许可以被改变,以避免这一点(例如,使用:
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)
Run Code Online (Sandbox Code Playgroud)
确保Range不是指针);但我现在无法做出改变。相反,我想以某种方式向编译器表明,我的真正意思是只有一个模板参数,而不是指定一个参数并推导出另一个模板参数。
我可以这样做吗?
感谢 C++11 和 C++14 的答案;涉及演绎指南的 C++17 答案不太相关,但如果您有,请发布(对于未来的 NVCC 版本......)
更新: strf 库本身已更新以规避这种情况,但问题仍然存在。
wal*_*nut 16
template<typename T>
inline constexpr auto range1_ptr = strf::range<T>;
template<typename T>
inline decltype(auto) range1(T begin, T end) {
return range1_ptr<T>(begin, end);
}
Run Code Online (Sandbox Code Playgroud)
然后调用range1而不是strf::range.
range1_ptr<T>(...)总是可以用来显式调用带有一个模板参数的模板,但不从参数中进行任何推论。range1复制从原始strf::range模板的推论。
这是有效的,因为[temp.deduct.funcaddr]/1表示在获取没有转换目标类型的函数的地址时,模板参数推导是在每个候选函数模板上完成的,就好像假设调用的参数和参数列表是空的。因此,不能为具有两个模板参数的第二个重载推导出第二个模板参数。剩下的唯一候选是第一个重载,它将被选为函数指针的目标。
只要没有第二个候选函数模板可以形成只有一个参数的有效模板 ID,range1_ptr就可以始终使用明确地调用一个参数的函数模板。否则,实例化range1_ptr会因为歧义而报错。
max*_*x66 11
通过一个using?
using tfp = void(*)(char const *, char const *);
tfp x = &strf::range;
char const * a = "abcd";
(*x)(a, a+2);
Run Code Online (Sandbox Code Playgroud)