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_);
}
哇,这是奇怪的。 C++充满了拐杖,因为我看到=((深入到C++中,我发现它有更多的缺点。THX FOR ANSWER –