I have a Foo
class template with two template parameters, and a constructor using a vector.
I also define some aliases for (partial) specializations (FooOne
, FooTwo
, FooThree
). I want the user to not have to worry about the types of these (and size of FooThree
).
I also want the user to be able to make Foo
from bytes; however, since I already have a constructor with the same prototype and it's not an intuitive way to build Foo
, I want it as a separate function makeFromBytes
.
#include <array>
#include <vector>
template <typename T, size_t S>
class Foo
{
public:
Foo() { }
Foo(const std::vector<T>& data) { /* ... */ }
template <typename T, size_t S>
friend Foo<T, S> makeFromBytes(const std::vector<char>& bytes);
private:
std::array<T, S> m_data{ };
};
template <typename T, size_t S>
Foo<T, S> makeFromBytes(const std::vector<char>& bytes)
{
Foo<T, S> result{ };
/* ... */
return result;
}
template <size_t S>
using FooOne = Foo<char, S>;
template <size_t S>
using FooTwo = Foo<int, S>;
using FooThree = Foo<int, 4>;
The syntax I want the user to use would look like this: makeFromBytes<FooOne<2>>
and makeFromBytes<FooThree>
that translate into makeFromBytes<char, 2>
and makeFromBytes<int, 4>
respectively.
I have tried many syntaxes (and googling) but it seems like C++ doesn't allow it.
Is there any way to get this clean syntax ? Other solutions are :
makeFromBytes<char, 2>()
, but the user has to be aware of FooOne's definition;using valueType = T;
in Foo and then using makeFromBytes<FooOne<2>::valueType, 2>()
;makeFromBytes
.Am I missing something with the syntax ? Is there any trick or better solution ? Thanks for your help.
You were really close to the solution. To get the syntax you desire, you only need to implement the function you declared:
template <class C>
C makeFromBytes(const std::vector<char>& bytes) {
C result{ }; // C is Foo<T, S>
/* ... */
return result;
}
If from within foo you need T or S, you can declare them in your class:
template <typename T, size_t S>
class Foo
{
public:
using value_type = T;
static constexpr size_t size = S;
// ...
};
Then use it inside the function:
template <class C>
C makeFromBytes(const std::vector<char>& bytes) {
C result{ }; // C is Foo<T, S>
using T = typename C::value_type;
static constexpr size_t S = C::size;
/* ... */
return result;
}