C++模板函数重载解析错误

问题描述:

namespace Random 
{ 
    std::mt19937 engine_{ std::random_device{}() }; 

    template<class T, class = std::enable_if_t<std::is_integral<T>::value>> 
    auto get(T from, T to) 
    { 
     return std::uniform_int_distribution<T>{from, to}(engine_); 
    } 

    template<class T, class = std::enable_if_t<std::is_same<T, float>::value>> 
    auto get(T from, T to) 
    { 
    return std::uniform_real_distribution<T>{from, to}(engine_); 
    } 

} 
int main() 
{ 
    std::cout.sync_with_stdio(false); 
    std::cout.setf(std::ios_base::boolalpha); 
    std::cout << Random::get<float>(1.0f, 2.5f);//COMPILE TIME ERROR 
    std::cin.get(); 
} 

编译器输出: 18:4:错误:重新定义 '型板T随机::得到(T,T)' 12:4:注:“型板T随机:: get(T,T)'此前在此处声明 在函数'int main()'中: 28:44:错误:没有用于调用'get(float,float)'的匹配函数' 28:44:note:candidate is : 12:4:注:型板T随机::得到(T,T) 12:4:注:模板参数推导/置换失败:C++模板函数重载解析错误

这项工作很好:

#include <type_traits> 
#include <random> 
#include <iostream> 

namespace Random 
{ 
    std::mt19937 engine_{ std::random_device{}() }; 

    template<class T, class = std::enable_if_t<std::is_integral<T>::value>> 
    auto get(T from, T to) 
    { 
     return std::uniform_int_distribution<T>{from, to}(engine_); 
    } 

    template<class T, class = std::enable_if_t<std::is_same<T, float>::value>> 
    T get(T from, T to) 
    { 
    return std::uniform_real_distribution<T>{from, to}(engine_); 
    } 

} 
int main() 
{ 
    std::cout.sync_with_stdio(false); 
    std::cout.setf(std::ios_base::boolalpha); 
    std::cout << Random::get<float>(1.0f, 2.5f);//GOOD 
    std::cin.get(); 
} 

这:

#include <type_traits> 
#include <random> 
#include <iostream> 

namespace Random 
{ 
    std::mt19937 engine_{ std::random_device{}() }; 

    template<class T, class = std::enable_if_t<std::is_integral<T>::value>> 
    auto get(T from, T to) 
    { 
     return std::uniform_int_distribution<T>{from, to}(engine_); 
    } 

    template<class T> 
    std::enable_if_t<std::is_same<T, float>::value, T> 
    get(T from, T to) 
    { 
     return std::uniform_real_distribution<T>{from, to}(engine_); 
    } 

} 
int main() 
{ 
    std::cout.sync_with_stdio(false); 
    std::cout.setf(std::ios_base::boolalpha); 
    std::cout << Random::get<float>(1.0f, 2.5f);//GOOD 
    std::cin.get(); 
} 

为什么编译器不能解析该决议在第一个例子?

默认参数不是签名的组成部分,所以你比较

template <typename T, typename> 
auto get(T, T) { /* implementation1 */ } 

VS

template <typename T, typename> 
auto get(T, T) { /* implementation2 */ } 

这被看作是相同的签名(即使推断返回类型将有所不同)

在您的工作示例中,您有不同的签名(即使将自动推算为T)

template <typename T, typename> 
auto get(T, T) { /* implementation1 */ } 

VS

template<class T, typename> 
T get(T, T) { /* implementation2 */ } 

template <typename T> 
std::enable_if_t<std::is_same<T, float>::value, T> 
get(T, T) { /* implementation2 */ } 

和呼叫一点也不含糊感谢SFINAE。

的其他方式,让auto返回类型和使用SFINAE将

template<class T, std::enable_if_t<std::is_integral<T>::value>* = nullptr> 
auto get(T from, T to) 
{ 
    return std::uniform_int_distribution<T>{from, to}(engine_); 
} 

template<class T, std::enable_if_t<std::is_same<T, float>::value>* = nullptr> 
auto get(T from, T to) 
{ 
    return std::uniform_real_distribution<T>{from, to}(engine_); 
} 
+0

哇,这是奇怪的。 C++充满了拐杖,因为我看到=((深入到C++中,我发现它有更多的缺点。THX FOR ANSWER –