Reputation: 1526
Here is something I have:
template <typename T, std::size_t dim>
struct vector;
template <std::size_t dim>
struct vector<float, dim>
{
// I want this implementation for dim <= 4
}
template <std::size_t dim>
struct vector<float, dim>
{
// I want this implementation for dim > 4
}
int main() {
vector<float, 3> v1; // should instantiate first one
vector<float, 7> v2; // should instantiate second one
}
Right now, this is not a working example of course, since I can't get it to work. I don't know how to arrange the specialization template signatures. They are same template arguments right now and won't compile. Somehow, a kind of SFINAE should enter the picture I guess but I am not allowed to have default template arguments on partial specializations.
I could use constexpr if
to handle the code selection and have one specialization instead. But I believe, having seperate specializations for these makes things more readable and manageable.
How would you achieve this?
Upvotes: 2
Views: 574
Reputation: 12928
You can achieve this by using SFINAE. You add an extra template parameter to the unspecialized template, then you make sure to match it in your specialization for a certain condition.
template <typename T, std::size_t dim, typename = void>
struct vector;
template <std::size_t dim>
struct vector<float, dim, std::enable_if_t<(dim <= 4)>>
{
// I want this implementation for dim <= 4
};
template <std::size_t dim>
struct vector<float, dim, std::enable_if_t<(dim > 4)>>
{
// I want this implementation for dim > 4
};
int main() {
vector<float, 3> v1; // should instantiate first one
vector<float, 7> v2; // should instantiate second one
}
std::enable_if_t
will deduce to void
by default if the condition passed to it is true. If not, it will not deduce to anything resulting in substitution failure leaving the way for any other template to match.
std::enable_if_t
requires c++14
but you can use typename std::enable_if<condition>::type
since c++11
.
Upvotes: 7
Reputation: 75697
With concepts you can simply write:
template <typename T, std::size_t dim>
struct vector;
template <std::size_t dim>
requires (dim <= 4)
struct vector<float, dim>
{
// I want this implementation for dim <= 4
};
template <std::size_t dim>
requires (dim > 4)
struct vector<float, dim>
{
// I want this implementation for dim > 4
};
See it on godbolt
We just have to wait for them
Upvotes: 1
Reputation: 2250
Possible solution using additional layer. We use additional bool
template argument and specialization for this arg. Can be used for version less than С++11.
template <typename T, std::size_t dim, bool moreThanFour>
struct vectorImpl;
template <std::size_t dim>
struct vectorImpl<float, dim, false>
{
// I want this implementation for dim <= 4
};
template <std::size_t dim>
struct vectorImpl<float, dim, true>
{
// I want this implementation for dim > 4
};
template <typename T, std::size_t dim>
struct vector : public vectorImpl < T, dim, (dim > 4) > {};
int main() {
vector<float, 3> v1; // should instantiate first one
vector<float, 7> v2; // should instantiate second one
}
Upvotes: 3