[英]C++ template function overload resolution bug
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:錯誤:'template T Random :: get(T,T)'的重新定義12:4:注意:'template 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();
}
為什么在第一個示例中編譯器無法解決該分辨率?
默認參數不是簽名的一部分,因此您可以進行比較
template <typename T, typename>
auto get(T, T) { /* implementation1 */ }
與
template <typename T, typename>
auto get(T, T) { /* implementation2 */ }
被視為相同的簽名(即使推導的返回類型會有所不同)
在您的工作示例中,您具有不同的簽名(即使將auto推導為T)
template <typename T, typename>
auto get(T, T) { /* implementation1 */ }
與
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_);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.