'Specialize template function to return vector
Let's say I have a reader class over a file:
class Reader {
public:
template <class T>
T Read();
};
Its only function is the Read function that reads any arithmetic type (static_assert(std::is_arithmetic_v<T>)) from a file. Now I want to create a specialization of that function, which reads a vector from the file. How would I go about doing that with templates? Something like the following doesn't work:
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>>();
^ ~~~~~~~~~~~~~~~~
Solution 1:[1]
You can't partially specialize functions. You can overload them though, but the way of doing it is not obvious, since your function doesn't take any parameters.
First, you need a way to check if a type is a std::vector<??>:
template <typename T> struct IsVector : std::false_type {};
template <typename ...P> struct IsVector<std::vector<P...>> : std::true_type {};
Then you can plug it into requires:
template <typename T>
T Read()
{
// Generic overload
}
template <typename T> requires IsVector<T>::value
T Read()
{
// Vector overload
}
Alternatively, you could have a single function, with if constexpr (IsVector<T>::value) inside.
Solution 2:[2]
A way to implement what you want is to delegate the logic of your member function to a couple of private member functions:
#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>>();
}
This doesn't require you to introduce new type traits to check if your type is a std::vector<>. However, it requires your return types to be default constructible.
Output:
T
std::vector<T>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | HolyBlackCat |
| Solution 2 | paolo |
