Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to deprecate implicit conversion while allowing explicit conversion?

Suppose I have a simple Duration class:

class Duration
{
    int seconds;
public:
    Duration(int t_seconds) : seconds(t_seconds) { }
};

int main()
{
    Duration t(30);
    t = 60;
}

And I decide that I don't like being able to implicitly convert from int to Duration. I can make the constructor explicit:

class Duration
{
    int seconds;
public:
    explicit Duration(int t_seconds) : seconds(t_seconds) { }
};

int main()
{
    Duration t(30); // This is fine, conversion is explicit
    t = 60; // Doesn't compile: implicit conversion no longer present for operator=
}

But what if I don't want to immediately break all calling code that's implicitly converting to Duration? What I would like to have is something like:

class Duration
{
    int seconds;
public:
    [[deprecated]]
    Duration(int t_seconds) : seconds(t_seconds) { }

    explicit Duration(int t_seconds) : seconds(t_seconds) { }
};

int main()
{
    Duration t(30); // Compiles, no warnings, uses explicit constructor
    t = 60; // Compiles but emits a deprecation warning because it uses implicit conversion
}

This would allow existing code to compile while identifying any places that currently rely on implicit conversion, so they can either be rewritten to use explicit conversion if it's intended or rewritten to have correct behavior if not.

However this is impossible because I can't overload Duration::Duration(int) with Duration::Duration(int).

Is there a way to achieve something like this effect short of "Make the conversion explicit, accept that calling code won't compile until you've written the appropriate changes"?

like image 396
Nathan Pierson Avatar asked Dec 02 '21 16:12

Nathan Pierson


People also ask

Which type conversion is more useful implicit or explicit?

It is implicit conversion when a smaller data type is converted into a larger data type or derived class into a base class. On the other hand, the conversion in the opposite direction is known as explicit conversion. It needs a cast operator to convert higher data type into a smaller data type.

Why do we need type casting write down some differences between implicit type casting and explicit type casting?

implicit casting doesn't require a casting operator. Explicit type casting is performed by the programmer. In this type casting programmer tells compiler to type cast one data type to another data type using type casting operator.

Why are implicit type conversions safe?

Implicit Conversions There is no special syntax for this type of conversion, this is the safest type of casting. No data is lost, for example, when converting from smaller to larger integral types or derived classes to base classes.

What is implicitly and explicitly in C#?

"Something that is implicit is expressed in an indirect way." "If a quality or element is implicit in something, it is involved in it or is shown by it;" Explicit. "Something that is explicit is expressed or shown clearly and openly, without any attempt to hide anything"


1 Answers

You can turn Duration(int t_seconds) into a template function that can accept an int and set it to deprecated.

#include<concepts>

class Duration {
  int seconds;
public:
  template<std::same_as<int> T>
  [[deprecated("uses implicit conversion")]]
  Duration(T t_seconds) : Duration(t_seconds) { }
  
  explicit Duration(int t_seconds) : seconds(t_seconds) { }
};

If you allow t = 0.6, just change the same_as to convertible_to.

Demo.

like image 182
康桓瑋 Avatar answered Oct 06 '22 13:10

康桓瑋