繁体   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