我有一个Vector类和一个Span类(有点像 std 类),我希望 Vector 可以转换为 Span。这基本上是有效的,但是在调用模板函数时,模板参数推导失败,我仍然遇到一个问题,而且我不明白为什么。
这是一个最小的示例(和编译器资源管理器链接):
template <class T>
struct Span {};
template <class T>
struct Vector
{
operator Span<T>() { return {}; }
};
void print_span_int(Span<int>);
template <class T>
void print_span(Span<T>);
void test()
{
Vector<int> vec;
print_span_int(vec); // ok
print_span(vec); // error
}
Run Code Online (Sandbox Code Playgroud)
我尝试添加推导指南,但这没有帮助:
template <class T>
Span(Vector<T>&) -> Span<T>;
print_span(Span(vec)); // now I can do that though :|
Run Code Online (Sandbox Code Playgroud)
是否可以print_span(vec);在不Vector继承的情况下进行编译Span?
您不能隐式转换为推导类型,或者更确切地说:推导 deos 不考虑隐式转换。您期望Vector<int>转换为Span<int>,但原则上有无限数量的潜在候选人。可能有一个Span<foo>可以从Vector<int>. Span<bar>也可以构建不同的专业化Vector<int>。一般来说,检查所有可能的组合是不可能的,并且经常会导致歧义。在您的示例中,情况并非如此,尽管甚至没有尝试走这条路线,但推导时不考虑隐式转换。出路是不依赖隐式转换。
基本思想是让print_span接受所有类型T,但然后将其限制为仅那些可以转换为Span<T::value_type>. 我对概念不太熟悉,所以我将向您展示有点老套的 sfinae 方式,尽管如果您熟悉概念,那么现代化它应该是直截了当的。
#include <type_traits>
#include <iostream>
template <class T> struct Vector;
template <class T>
struct Span {
using value_type = T;
};
template <class T>
struct Vector {
using value_type = T;
operator Span<T>() { return {}; }
};
template <class T>
Span(Vector<T>&) -> Span<T>;
template <class T>
void print_span(Span<T>) { std::cout << "span<T>\n";}
template <class T>
std::enable_if_t<std::is_convertible_v< T,Span< typename T::value_type>>,void>
print_span(const T& t){ std::cout << "T\n"; }
int main() {
Vector<int> vec;
print_span(Span(vec));
print_span(vec);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
466 次 |
| 最近记录: |