簡體   English   中英

C ++模板函數重載解析錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM