This question is mostly to understand the logic and naming conventions in the design of the cast functions. Here, I simply pick the example of const_cast and then I give the example of a custom cast function.

I could be wrong, but in my opinion cast functions are way to tell the compiler something that we know and the compiler doesn't know and to bypass certain rules in the process if necessary. At least this is the logic in all built in cast functions (reinterpret_cast, const_cast, dynamic_cast, and C-casts).

So the example is simple, if I have an object const A. I can produce a non-const reference:

A const a;
A& a2 = const_cast<A&>(a); // I "know" from the logic of the code, or from the nature of the compiler, or from the system environment, that 'a' can *really* be modified

I could write a function,

A& to_non_const(A const& a){return const_cast<A&>(a);}

and use it like this

A const a;
A& a2 = to_non_const(a);

The first question is, why is const_cast redundant in the parametrized type?, why isn't there a function to_non_const that automatically deduces the full target type?

I know how to use const_cast, but I mostly want to know the logic about it as a guideline to write other custom "cast" function. This is example of a custom cast function,

template<class T>
struct positive{ // nothing private for simplicity
  T val_;
  positive(T const& t) : val_(t){if(t < 0) throw std::domain_error("number is negative");}
  ...
};
double cinco = 5;
positive<double> p(cinco); // ok, but checks
positive<double> p = positive_cast<positive<double>>(cinco); // I "know" it is positive

where

template<class Positive, class T>
Positive positive_cast(T const& t){
   Positive ret; 
   ret.val_ = t; // assigns with no check
   return ret;
}

The idea here is that I have a cast function that bypassed the check. (For example, imagine, because the check is expensive.) In other words, I am doing something locally unsafe (to the logic of the program), but a bit safer and controlled than positive<double> p = reinterpret_cast<positive<double> const&>(cinco);.

Is this a good a design, I replicated the const_cast logic, and I could do it in a simpler way.

template<class T>
positive<T> to_positive(T const& t){
   return positive_cast<positive<T>>(t);
}

Used as this:

double cinco = 5;
positive<double> p(cinco); // ok, but checks
positive<double> p = to_positive(cinco); // I "know" it is positive

Would this be a consistent correct "cast" function? Using the "cast" version from before I can make it clear that there is no check, but to_positive can be understood as having a check.

There are no serious discussions around of how an unsafe cast function should be written and what conventions to follow. It looks like some people call "cast" to any conversion function regardless of the semantics.

I found some other examples around, but it is hard to find a common pattern.

In all the cases I could see the cast behave like functions and they are explicit in the target type, and in general there are no convenience functions that deduce parameters automatically.

Finally, to summarize. Is there agreement of what a cast function is? Is any conversion a cast? In the language it seems to imply also some sort of unchecked conversion. I am looking for a guideline or a good example of a cast function.

3 upvote
  flag
"I "know" from the logic of the code that 'a' can really be modified" You know wrong, because modifying a const object is undefined behaviour. – juanchopanza
upvote
  flag
@juanchopanza, do you think dynamic_cast would have been a better example? I can change it to that. – alfC
upvote
  flag
@juanchopanza, I am not sure UB invalidates the question. If const_cast is there is because the programmer knows something that compiler doesn't, including knowing that the risk of something bad (undefined) happening is low (or near zero). – alfC
2 upvote
  flag
It would definitely make casting away const more convenient to deduce the target type instead of requiring its specification, like mutable(foo) instead of const_cast<Foo&>(foo), but not sure it's a good idea to be making casts convenient. Stroustrup actually deliberately tried to make casting lengthy to write and inconvenient to do to discourage it. – Team Upvote
upvote
  flag
@TeamUpvote, I agree. This is a valid explanation for the const_cast case. I agree that (if not were for the deliberate inconvenience) mutable would be a good name. Also even a hypotetical const_cast_ function could have effectively two versions, one with type deduction and another with target type explicit. – alfC
upvote
  flag
Please use quotations only for quotations. I've edited the text and removed the > characters. – Christian Hackl
upvote
  flag
So what is the question, exactly? You seem to agree that const_cast should be hard to write so as to discourage programmers from using it lightly. If the question is whether your to_positive is a good idea or not, perhaps Code Review Stack Exchange might be a better fit. – Christian Hackl
upvote
  flag
@ChristianHackl, the question is whether there is agreement of what a cast function really is. Is any conversion a cast? in the language it seems to imply also some sort of unchecked conversion. So I am looking for a guideline or a good example of a cast function. – alfC
1 upvote
  flag
@alfC: const_cast et al are not functions but built-in operators. They should not be seen as a design guideline for conversion functions in your own code. – Christian Hackl
upvote
  flag
@ChristianHackl, Often built-in language designs propagate into custom program design, but good point. I guess I saw many functions named cast_something that partially imitated built-in operations. – alfC

0 Answers 11

Not the answer you're looking for? Browse other questions tagged or ask your own question.