Специализация шаблона на основе сравнения целочисленных констант - PullRequest
2 голосов
/ 11 марта 2019

Вот что у меня есть:

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
}

Сейчас, конечно, это не рабочий пример, так как я не могу заставить его работать. Я не знаю, как организовать подписи шаблона специализации. Они являются теми же аргументами шаблона прямо сейчас и не будут компилироваться. Так или иначе, вид SFINAE должен войти в картину, я думаю, но мне не разрешено иметь аргументы шаблона по умолчанию для частичных специализаций.

Я мог бы использовать constexpr if для обработки выбора кода и иметь одну специализацию вместо этого. Но я считаю, что наличие отдельных специализаций для этих целей делает вещи более читабельными и управляемыми.

Как бы вы этого достигли?

Ответы [ 3 ]

6 голосов
/ 11 марта 2019

Вы можете достичь этого, используя SFINAE. Вы добавляете дополнительный параметр шаблона к неспециализированному шаблону, а затем убедитесь, что он соответствует вашей специализации для определенного условия.

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 по умолчанию выведет void, если переданное ему условие истинно. В противном случае это не приведет к чему-либо, что приведет к сбою замещения, оставляя путь для любого другого шаблона для сопоставления.

std::enable_if_t требуется c++14, но вы можете использовать typename std::enable_if<condition>::type, поскольку c++11.

3 голосов
/ 11 марта 2019

Возможное решение с использованием дополнительного слоя. Мы используем дополнительный bool шаблонный аргумент и специализацию для этого аргумента. Может использоваться для версии ниже С ++ 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
}
1 голос
/ 11 марта 2019

С понятиями вы можете просто написать:

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
};

Посмотреть на Годболт

Мы просто должны ждать их

...