了解SFINAE示例

时间:2014-12-02 17:11:22

标签: c++ c++11 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 个答案:

答案 0 :(得分:5)

decltype未评估的上下文。它只是在类型级别上运行,所以知道dist的主体,无论它在哪里,都返回一些类型X就足够了。

答案 1 :(得分:0)

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