Могу ли я перегрузить переменные шаблона?

Я хочу объявить что-то вроде этого:

template <typename T>
constexpr enable_if_t<is_integral_v<T>, int[]> foo = { 1, 2 };

template <typename T>
constexpr enable_if_t<is_floating_point_v<T>, int[]> foo = { 10, 20, 30 };

Но когда я пытаюсь я получаю эту ошибку:

ошибка: повторное объявление template<class T> constexpr std::enable_if_t<std::is_floating_point<_Tp>::value, int []> foo
примечание: предыдущее объявление template<class T> constexpr std::enable_if_t<std::is_integral<_Tp>::value, int []> foo<T>

Я чувствую, что это должно быть законным, поскольку для любого данного аргумента шаблона никогда не будет определено более одного foo. Могу ли я что-то сделать, чтобы помочь компилятору понять это?


person Jonathan Mee    schedule 14.06.2019    source источник
comment
@VTT Может быть, вы можете уточнить? Вы говорите, что это должно быть возможно? Если да, то как?   -  person Jonathan Mee    schedule 14.06.2019


Ответы (1)


Не с перегрузкой.

Ваше объявление с enable if в порядке, но вы не можете иметь несколько из них, поскольку переменные не перегружаются.

Со специализацией, как и с классами, все работает отлично:

#include <iostream>
#include <type_traits>

using namespace std;

template <typename T, typename = void>
constexpr int foo[] = {10, 20, 30};

template <typename T>
constexpr int foo<T, enable_if_t<is_integral_v<T>>>[] = { 1, 2 };


int main() {
    cout << foo<int>[0] << endl;
    cout << foo<float>[0] << endl;
}

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

Живой пример

person Guillaume Racicot    schedule 14.06.2019
comment
Этот код компилируется? Пока компилятор msvc жалуется ('std::array': для использования шаблона класса требуется список аргументов шаблона) - person vahancho; 14.06.2019
comment
@vahancho да, он компилируется. Я добавил ссылку на проводник компилятора. Сообщите об ошибке, если ваша реализация не поддерживает CTAD - person Guillaume Racicot; 14.06.2019
comment
@vahancho обязательно скомпилируйте с включенным C++ 17 - person Fureeish; 14.06.2019
comment
@vahancho: вам понадобится С++ 17. В этом коде используются руководства по дедукции. Здесь представлена ​​версия, совместимая с руководством по предварительной дедукции. - person AndyG; 14.06.2019
comment
@Fureeish Ну, тогда стоит упомянуть, что он не компилируется компилятором (компиляторами) MS. Например: godbolt.org/z/M53dq1 (-std=c++17 -O3). Я ошибаюсь? - person vahancho; 14.06.2019
comment
@vahancho msvc имеет другой стиль аргументов командной строки: godbolt.org/z/Xjai2A (/std:c ++17/О2) - person Guillaume Racicot; 14.06.2019
comment
@GuillaumeRacicot, а, хорошо. Спасибо. - person vahancho; 14.06.2019
comment
Я думаю, что это не работает для меня из-за моего определения массива. Я пробовал здесь: ideone.com/fp5TEr Как мне объявить это int[]? - person Jonathan Mee; 14.06.2019
comment
@JonathanMee Я заменил синтаксис массива в стиле c. квадратные скобки после угловых скобок шаблона. - person Guillaume Racicot; 14.06.2019
comment
@JonathanMee: вам не хватает угловой скобки: Исправлено. Гийом уже упомянул о неправильном расположении квадратных скобок. - person AndyG; 14.06.2019
comment
@AndyG Великолепно, спасибо, ребята, за это я скоро приму. Это именно то, что я ищу. - person Jonathan Mee; 14.06.2019
comment
@AndyG и Guillaume Racicot Это отлично сработало для меня в моем игрушечном примере, но когда я перешел к использованию массива указателей на функции, он перестал работать. Я добавил дополнительный вопрос здесь: stackoverflow.com/q/56649481/2642059 Не знаю, если вы, ребята будет иметь какое-либо последующее понимание, но я подумал, что опубликую на всякий случай. - person Jonathan Mee; 18.06.2019