Понимание примера SFINAE
Мне трудно понять этот фрагмент кода, который использует SFINAE.
template <typename T>
auto dist() -> typename std::enable_if<std::is_integral<T>::value,
std::uniform_int_distribution<T>>::type;
template <typename T>
auto dist() -> typename std::enable_if<std::is_floating_point<T>::value,
std::uniform_real_distribution<T>>::type;
...
decltype(dist<float>()) unifDistFloat;
decltype(dist<int>()) unifDistInt;
dist()
является именем двух различных прототипов функций, поэтому нет тела, содержащего оператор return. Это означает, что он никогда не возвращает значение типа uniform_real_distribution<T>
или uniform_int_distribution<T>
.
Так не должно ли decltype
потерпеть неудачу при попытке вызвать неполную функцию? Или decltype
просто не вызывает функцию вообще, а вместо этого просто вычисляет возвращаемый тип?
2 ответа:
decltype
является недооцененным контекстом. Он просто работает на уровне типа, поэтому достаточно знать, что телоdist
, где бы оно ни находилось, возвращает некоторый тип X.
decltype
спецификатор проверяет объявленный тип сущности или запрашивает возвращаемый тип выражения, вот что он делает.Здесь альтернативное использование. для того, чтобы показать, что
decltype
заботится только о типе любого проходящего выраженияtemplate<typename U > static typename std::enable_if<std::is_same<U, int>::value, std::uniform_int_distribution <U>>::type dist(); // NOTE: no function body template<typename U > static typename std::enable_if<std::is_same<U, double>::value, std::uniform_real_distribution <U>>::type dist() { //return; // NOTE: no return } decltype(dist<T>()) mUniformDistribution;
Вероятно, вопрос, почему компилятор жалуется на функцию dist () как на неполную? я понятия не имею, почему это так.
Демонстрационный пример
template<typename T > class Random { public: Random(const T& min, const T& max) : mUniformDistribution(min, max) {} T operator()() { return mUniformDistribution(mEngine); } private: std::default_random_engine mEngine{ std::random_device()() }; template<typename U > static typename std::enable_if<std::is_same<U, int>::value, std::uniform_int_distribution <U>>::type dist(); // NOTE: no function body template<typename U > static typename std::enable_if<std::is_same<U, double>::value, std::uniform_real_distribution <U>>::type dist() { //return; // NOTE: no return } decltype(dist<T>()) mUniformDistribution; }; int main() { Random<int> getRandom(0, 9); for (int i = 0; i<9; ++i) std::cout << getRandom() << '\n'; }