Я хочу отправить вызов из фабричного шаблона функции в структуру, которая частично специализирована, на основе типа возврата:
#include <array>
template<typename Type, typename Enable=void>
struct make_it;
template<typename A>
struct make_it<std::array<A, 3>>
{
static std::array<A, 3> apply()
{
return {A{0}, A{1}, A{2}};
}
};
template<typename A>
struct make_it<std::array<A, 4>>
{
static std::array<A, 4> apply()
{
return {A{0}, A{0}, A{0}, A{0}};
}
};
template<typename T>
constexpr bool greater(T&& a, T&& b)
{
return a > b;
}
template<typename T, int N>
struct make_it<std::array<T, N>, std::enable_if_t<greater(N,4)>>
{
static std::array<T, N> apply()
{
return std::array<T,N>{};
}
};
template<typename Type>
Type make()
{
return make_it<Type>::apply();
}
int main()
{
auto a = make<std::array<double,3>>();
auto b = make<std::array<double,4>>();
auto c = make<std::array<double,5>>();
}
Скомпилировано с
g++ -O3 -std=c++2a -Wall -Wpedantic -Wunused-parameter -I /usr/include main.cpp -o main
с использованием g++ (GCC) 8.2.1 20181127
это приводит к ошибке
main.cpp: In instantiation of ‘Type make() [with Type = std::array<double, 5>]’:
main.cpp:49:41: required from here
main.cpp:42:32: error: incomplete type ‘make_it<std::array<double, 5>, void>’ used in nested name specifier
return make_it<Type>::apply();
Что-то не так с линией SFINAE
struct make_it<std::array<T, N>, std::enable_if_t<greater(N,4)>>
Я подумал, что это должно частично специализировать make_it
, включить шаблон для всех N > 4
.Так что если N == 5
, этот шаблон становится "видимым", и он, безусловно, лучше подходит для вызова
auto c = make<std::array<double,5>>();
, чем неполный тип?Что здесь происходит?