Понимание примера 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'; }