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 Random :: get(T,T)' 12:4:注意:'模板T Random :: get(T,T)'先前在这里声明 在函数'int main()'中: 28:44:错误:没有匹配函数来调用'get(float,float)' 28:44:注意:候选人是: 12:4:注意:模板T Random :: get(T,T) 12:4:注意:模板参数扣除/替换失败:
这项工作很好:
#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();
}
为什么编译器在第一个示例中无法解析此解决方案?
答案 0 :(得分:0)
默认参数不是签名的一部分,因此您需要进行比较
template <typename T, typename>
auto get(T, T) { /* implementation2 */ }
VS
template <typename T, typename>
auto get(T, T) { /* implementation1 */ }
被视为相同的签名(即使推断的返回类型不同)
在您的工作示例中,您有不同的签名(即使自动推断为T)
template<class T, typename>
T get(T, T) { /* implementation2 */ }
VS
template <typename T>
std::enable_if_t<std::is_same<T, float>::value, T>
get(T, T) { /* implementation2 */ }
或
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_);
}
返回类型并使用SFINAE的方法是
`curl -s -u #{username}:#{password} #{HTTPS_PAGE_URL}`