Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

explicit constructor still doing conversions

Tags:

c++

I have a (very) simple templated type that lets me return a "IsValid" flag when returning from functions. It goes as follows:

template <typename T>
struct Validated
{
private:
    T m_value;
    bool m_isValid;

public:
    Validated() : m_value(), m_isValid(false) {}
    explicit Validated(T const& value) : m_value(value), m_isValid(true) {}
    explicit Validated(bool isValid, T const& value) : m_value(value), m_isValid(isValid) {}
    explicit Validated(bool isValid, T&& value) : m_value(value), m_isValid(isValid) {}    

    bool IsValid() const { return m_isValid; }
    T const& Value() const { return m_value; }
};

Maybe there's something I don't understand with the explicit specifier, but I was wondering why the following works just fine, and how could I avoid the conversion from bool to double?

void someFunc()
    {
    Validated<double> foo(1.0); // this makes perfect sense
    Validated<double> bar(true); // works... (sets m_value to 1.0)
    }

Been looking at similar questions/answers but couldn't find any that is satisfactory. I am aware std::optional exists but we're not into c++17 yet. Tried this on VS2012/v110.

Update: as suggested, deleting the constructor for bool does the job (starting from c++14). It does not work for c++11 (VS2012/toolset v110).

like image 214
AlexG Avatar asked Apr 13 '26 07:04

AlexG


1 Answers

You can simply delete the constructor taking a single bool:

Validated(bool value) = delete;

Note: You may need some extra precautions if you want Validated<bool> to be a valid type.


You can also prevent construction from any type other than T (stronger than the previous one):

template <class U>
Validated(U) = delete;

This will work even with Validated<bool> because construction from T will match your Validated(T const&) overload while construction from any type other than T will match the deleted template.

This method would prevent (even explicit) construction of Validated<double> from 1, 1f, etc., so you may not want to use it.


explicit does not make your code ill-formed, it prevents implicit construction of a Validated<T> from a T, e.g.:

void f(Validated<double>);

f(1.0); // ill-formed because the conversion would be implicit
like image 198
Holt Avatar answered Apr 14 '26 22:04

Holt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!