簡體   English   中英

如何防止構造函數中的 bool 到 int 轉換?

[英]How to prevent bool to int conversion in constructor?

我有以下課程,盡可能接近我的生產代碼:

#include <iostream>

template <typename T>
struct M {

    M(std::string a, std::string b, T value = T(), const bool ready = false) : m_value{value}, m_ready{ ready } {}

    T m_value;
    bool m_ready;

};

auto main() -> int {
    {
        M<int> m{"a", "b"};
        std::cerr << m.m_value << std::endl;
    }
    {
        M<int> m{"a", "b", true};
        std::cerr << m.m_value << std::endl;
    }
}

在第一種情況下, m_value的值如預期的m_value為 0。 在第二個中它是 1,因為它采用 bool 的值。 有沒有辦法避免轉換?

您可以通過顯式刪除直接將bool作為第三個參數的版本來阻止轉換:

M(std::string, std::string, bool, bool = false) = delete;

但是,如果Tbool ,那將導致問題。 因此,您需要使用一些 SFINAE 體操來使此定義僅在T可轉換為bool實際上不是bool

我認為這有效

#include <iostream>
#include <type_traits>

template <typename T>
struct M {

    template <typename U=T, typename=std::enable_if_t<std::is_same_v<T, U>>>
    M(std::string a, std::string b, U value = U(), const bool ready = false) : m_value{value}, m_ready{ ready } {}

    T m_value;
    bool m_ready;

};

auto main() -> int {
    {
        M<int> m{"a", "b"};
        std::cout << m.m_value << std::endl;
    }
    {
        M<int> m{"a", "b", 1};
        std::cout << m.m_value << std::endl;
    }
    {
        // This does not compile
        // M<int> m{"a", "b", true};
        // std::cout << m.m_value << std::endl;
    }
    {
        // This compiles
        M<bool> m{"a", "b", true};
        std::cout << m.m_value << std::endl;
    }
    return 0;
}

您可以添加另一個構造函數來拒絕任何不完全是T

template <typename T>
struct M {
    M(std::string a, std::string b, T value = T(), const bool ready = false);

    template <typename U>
    M(std::string, std::string, U, bool = false) = delete;
};

M<int>("hello", hello", true)將更喜歡構造函數模板,該模板已被刪除。但請注意, M<int>("hello", "hello", '4')M<int>("hello", "hello", 4u)也是如此M<int>("hello", "hello", 4u) 。所以這是一個真正解決您要刪除哪些精確內容的問題。

如果你真的只想完全拒絕bool ,你可以通過約束模板來做到這一點:

template <typename U, std::enable_if_t<std::is_same_v<U, bool>, int> = 0>
M(std::string, std::string, U, bool = false) = delete;

或者,在 C++20 中:

template <std::same_as<bool> U>
M(std::string, std::string, U, bool = false) = delete;

或者:

M(std::string, std::string, std::same_as<bool> auto, bool = false) = delete;

這樣做仍然允許M<bool>可以從兩個string s 和一個bool構造,因為非模板構造函數仍然是更好的匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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