简体   繁体   中英

Template specialization based on integer constant comparison

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?

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 .

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
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM