将模板函数专门化为 return 向量
Specialize template function to return vector
假设我有一个 reader class 文件:
class Reader {
public:
template <class T>
T Read();
};
它的唯一功能是 Read
函数,可以从文件中读取任何算术类型 (static_assert(std::is_arithmetic_v<T>)
)。现在我想创建该函数的特化,它从文件中读取一个向量。我将如何使用模板来做到这一点?以下内容不起作用:
template <class T>
std::vector<T> Read<std::vector<T>>();
error: function template partial specialization is not allowed
std::vector<U> Read<std::vector<U>>();
^ ~~~~~~~~~~~~~~~~
您不能部分特化函数。虽然你可以重载它们,但这样做的方式并不明显,因为你的函数不带任何参数。
首先,您需要一种方法来检查类型是否为 std::vector<??>
:
template <typename T> struct IsVector : std::false_type {};
template <typename ...P> struct IsVector<std::vector<P...>> : std::true_type {};
然后你可以把它插入requires
:
template <typename T>
T Read()
{
// Generic overload
}
template <typename T> requires IsVector<T>::value
T Read()
{
// Vector overload
}
或者,您可以有一个函数,其中包含 if constexpr (IsVector<T>::value)
。
实现您想要的方法的一种方法是将您的成员函数的逻辑委托给几个私有成员函数:
#include <cstdio>
#include <vector>
class BinaryReader {
public:
template <class T>
T Read() {
T t{};
this->ReadImpl(t);
return t;
}
private:
template <class T>
void ReadImpl(T& t) {
static_assert(std::is_arithmetic_v<T>);
std::puts("T");
t = T{}; // implement your logic here
}
template <class T>
void ReadImpl(std::vector<T>& t) {
std::puts("std::vector<T>");
t = std::vector<T>{}; // implement your logic here
}
};
int main() {
BinaryReader br;
br.Read<int>();
br.Read<std::vector<int>>();
}
这不需要您引入新的类型特征来检查您的类型是否是 std::vector<>
。但是,它要求您的 return 类型是默认可构造的。
输出:
T
std::vector<T>
假设我有一个 reader class 文件:
class Reader {
public:
template <class T>
T Read();
};
它的唯一功能是 Read
函数,可以从文件中读取任何算术类型 (static_assert(std::is_arithmetic_v<T>)
)。现在我想创建该函数的特化,它从文件中读取一个向量。我将如何使用模板来做到这一点?以下内容不起作用:
template <class T>
std::vector<T> Read<std::vector<T>>();
error: function template partial specialization is not allowed
std::vector<U> Read<std::vector<U>>();
^ ~~~~~~~~~~~~~~~~
您不能部分特化函数。虽然你可以重载它们,但这样做的方式并不明显,因为你的函数不带任何参数。
首先,您需要一种方法来检查类型是否为 std::vector<??>
:
template <typename T> struct IsVector : std::false_type {};
template <typename ...P> struct IsVector<std::vector<P...>> : std::true_type {};
然后你可以把它插入requires
:
template <typename T>
T Read()
{
// Generic overload
}
template <typename T> requires IsVector<T>::value
T Read()
{
// Vector overload
}
或者,您可以有一个函数,其中包含 if constexpr (IsVector<T>::value)
。
实现您想要的方法的一种方法是将您的成员函数的逻辑委托给几个私有成员函数:
#include <cstdio>
#include <vector>
class BinaryReader {
public:
template <class T>
T Read() {
T t{};
this->ReadImpl(t);
return t;
}
private:
template <class T>
void ReadImpl(T& t) {
static_assert(std::is_arithmetic_v<T>);
std::puts("T");
t = T{}; // implement your logic here
}
template <class T>
void ReadImpl(std::vector<T>& t) {
std::puts("std::vector<T>");
t = std::vector<T>{}; // implement your logic here
}
};
int main() {
BinaryReader br;
br.Read<int>();
br.Read<std::vector<int>>();
}
这不需要您引入新的类型特征来检查您的类型是否是 std::vector<>
。但是,它要求您的 return 类型是默认可构造的。
输出:
T
std::vector<T>