Code example:

#include <iostream> #include <string> struct A { int a; explicit operator std::string() { return "<" + std::to_string(a) + ">"; } }; void f(std::string s) { std::cout << s << std::endl; } int main() { A a {1}; f(static_cast<std::string>(a)); f(std::string(a)); f((std::string)a); // f(boost::lexical_cast<std::string>(a)); return 0; } 

Question 2:

1) Is it possible to prohibit casting in C-style, so that the f(std::string(a)) or f((std::string)a) f(static_cast<std::string>(a)) compiler and f(static_cast<std::string>(a)) worked?

2) How to "teach" to trigger the call f(boost::lexical_cast<std::string>(a)) ?

  • one
    The B-style reduction is (T)var , not T(var) . The second is called function style cast . According to claim 1. I think it will not work out because in both cases, your transform operator is called. Those. in context, they are equivalent. If only static_cast in any macro not to wrap. But this is so, the thought is half awake. - 伪位蔚蠂慰位蠀蟿
  • @alexolut I understand, but it works this way and that. Added in question. - andy.37
  • Or maybe instead of operator std::string just make the toString method? - yrHeTaTeJlb
  • @yrHeTaTeJlb, alas, for some reason, I don鈥檛 feel like it. Optimally - lexical_cast - andy.37

2 answers 2

With regard to the prohibition of casting in the style of C, I can only advise to look in the direction of the compiler options. In GCC, for example, you can add the -Wold-style-cast and -Werror flags, then the C -Wold-style-cast will trigger a warning, and the warnings will be interpreted as errors.

With boost::lexical_cast everything is simple, you need to add a template specialization. Your example will look like this:

 #include <iostream> #include <string> #include <boost/lexical_cast.hpp> struct A { int a; explicit operator std::string() const{ return "<" + std::to_string(a) + ">"; } }; namespace boost{ template<> std::string lexical_cast<std::string, A>(const A& arg){ return std::string(arg); } }; void f(std::string s) { std::cout << s << std::endl; } int main() { A a {1}; f(static_cast<std::string>(a)); f(std::string(a)); f((std::string)a); f(boost::lexical_cast<std::string>(a)); return 0; } 
  • By the way, -Wold-style-cast does not provide for functional casting. - 伪位蔚蠂慰位蠀蟿
  • @alexolut, As for me, he should not. I never understood at all how much this is called a type conversion. It's just the creation of an anonymous object using a constructor with one parameter. - yrHeTaTeJlb
  • This is because a constructor without a explicit with one parameter is called transform. - 伪位蔚蠂慰位蠀蟿
  • But it should not due to the fact that this is not an old-style-cast . I mentioned this in the commentary to the question already. - 伪位蔚蠂慰位蠀蟿
  • Thank you, it works. Sorry for the delay. - andy.37

Understand some kind of crutch solution to ban conversions without static_cast :

 #include <iostream> #include <string> template <class T, class X> T my_cast(X&& x) { return static_cast<T>(x); } #define static_cast my_cast struct A { int a; private: explicit operator std::string() const { return "<" + std::to_string(a) + ">"; } template <class T, class X> friend T my_cast(X&& x); }; void f(std::string s) { std::cout << s << std::endl; } int main() { A a {1}; f(static_cast<std::string>(a)); // ok f(std::string(a)); // error f((std::string)a); // error return 0; } 
  • I do not want to produce crutches, but thanks anyway. - andy.37