c++ - Implicit conversion not happening -


the last question asked stumbled upon when trying understanding thing... can't understand (not day).

this quite long question statement, @ least hope question might prove useful many people , not me.

the code have following:

template <typename t> class v; template <typename t> class s;  template <typename t> class v { public:  t x;   explicit v(const t & _x)  :x(_x){}   v(const s<t> & s)  :x(s.x){} };  template <typename t> class s { public:  t &x;   explicit s(v<t> & v)  :x(v.x)  {} };  template <typename t> v<t> operator+(const v<t> & a, const v<t> & b) {  return v<t>(a.x + b.x); }  int main() {  v<float> a(1);  v<float> b(2);  s<float> c( b );   b = + v<float>(c); // 1 -- compiles  b = + c;           // 2 -- fails  b = c;               // 3 -- compiles   return 0; } 

expressions 1 , 3 work perfectly, while expression 2 not compile.

if have understood properly, happens is:

expression 1

  1. c is implicitly converted const using standard conversion sequence (consisting on 1 qualification conversion).
  2. v<float>(const s<t> & s) called , temporal const v<float> object generated (let's call t). const-qualified because temporal value.
  3. a converted const c.
  4. operator+(const v<float> & a, const v<float> & b) called, resulting in temporal of type const v<float> can call q.
  5. the default v<float>::operator=(const & v<float>) called.

am ok here? if made subtle mistake please, let me know, trying gain understanding implicit casting deep possible...

expression 3

  1. c converted v<float>. that, have user-defined conversion sequence:
    1.1. first standard conversion: s<float> const s<float> via qualification conversion.
    1.2. user-defined conversion: const s<float> v<float> via v<float>(const s<t> & s) constructor.
    1.3 second standard conversion: v<float> const v<float> via qualification conversion.
  2. the default v<float>::operator=(const & v<float>) called.

expression 2?

what not understand why there problem second expression. why following sequence not possible?

  1. c converted v<float>. that, have user-defined conversion sequence:
    1.1. initial standard conversion: s<float> const s<float> via qualification conversion.
    1.2. user-defined conversion: const s<float> v<float> via v<float>(const s<t> & s) constructor.
    1.3. final standard conversion: v<float> const v<float> via qualification conversion.
  2. steps 2 6 same in case of expression 1.

after reading c++ standard though: 'hey! maybe problem has to 13.3.3.1.2.3!' states:

if user-defined conversion specified template conversion function, second standard conversion sequence must have exact match rank.

but cannot case since qualification conversion has exact match rank...

i have no clue...

well, whether have answer or not, reading here :)

as edric pointed out, conversions not considered during template argument deduction. here, have 2 contexts template parameter t can deduced type of arguments:

template<class t> v<t> operator+(v<t> const&, v<t> const&);                ~~~~~~~~~~~  ~~~~~~~~~~~~ 

but try invoke function template v<float> on left-hand side , s on right hand side. template argument deduction results in t=float left hand side , you'll error right hand side because there no t v<t> equals s<t>. qualifies template argument deduction failure , template ignored.

if want allow conversions operator+ shouldn't template. there following trick: can define inline friend inside of class template v:

template<class t> class v { public:    v();    v(s<t> const&); // <-- note: no explicit keyword here     friend v<t> operator+(v<t> const& lhs, v<t> const& rhs) {       ...    } }; 

this way, operator not template anymore. so, there no need template argument deduction , invocation should work. operator found through adl (argument dependent lookup) because left-hand side v<float>. right-hand side converted v<float> well.

it possible disable template argument deduction specific argument. example:

template<class t> struct id {typedef t type;};  template<class t> t clip(    typename id<t>::type min,    t value,    typename id<t>::type max ) {    if (value<min) value=min;    if (value>max) value=max;    return value; }  int main() {    double x = 3.14;    double y = clip(1,x,3); // works, t=double } 

even though type of first , last argument int, not considered during template argument deduction because id<t>::type not so-called *deducible context`. so, t deduced according second argument, results in t=double no contradictions.


Comments

Popular posts from this blog

ASP.NET/SQL find the element ID and update database -

c++ - Compiling static TagLib 1.6.3 libraries for Windows -

PostgreSQL 9.x - pg_read_binary_file & inserting files into bytea -