Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

conversion operator with template functions

Tags:

c++

templates

stl

I have a class with a conversion operator to std::string. It works great with everything except with functions receiving std::basic_string<T> (templated on T).

#include <string>
struct A{
  operator std::string(){return std::string();}
};

void F(const std::basic_string<char> &){}
template<typename T> void G(const std::basic_string<T> &) {}

int main(){
  A a;
  F(a); // Works!
  G(a); // Error!
  return 0; // because otherwise I'll get a lot of comments :)
}

The error I receive is

error: no matching function for call to 'G(A&)'                                     
note: candidate is:
note: template<class T> void G(const std::basic_string<_CharT>&)

Now, I know I can define G as a friend in the struct A and it'll work, but my problem is with a lot of stl functions that already exist and receive std::basic_string<T> (for example, the operator<< printing function, or comparison operators, or many other functions.

I would really like to be able to use A as if it was an std::string. Is there any way to do this?

like image 358
rabensky Avatar asked Aug 07 '13 14:08

rabensky


2 Answers

I would really like to be able to use A as if it was an std::string. Is there any way to do this?

Yes, but are you sure you really want this? The solution is:

struct A : public std::string {
};

but recall that std::string doesn't have a virtual destructor and therefore, cannot be used polymorphically. You have been warned!!!

A str() is a far better solution and allows you to be explicit when you want to pass your A to a function taking a std::basic_string<T>.

like image 104
Cassio Neri Avatar answered Sep 29 '22 04:09

Cassio Neri


The compiler cannot infer that far; you'll either have to explicitly call the cast operator or to explictly specify the template parameter :

G(static_cast<std::string>(a));
G<char>(a); 

To understand why the compiler can't do both user-defined conversion and template argument deduction, let's take this example :

template<typename T>
struct Number {
    Number(double n) {};
    Number(int n) {};
};

struct A{
  operator Number<double>(){return Number<double>(1.);}
  operator Number<int>(){return Number<int>(1);}
};

template<typename T> void G(Number<T>& number) { }

int main(){
  A a;
  G(a); // What do I do ?!
  return 0;
}

What the compiler should do in that case ?

like image 36
zakinster Avatar answered Sep 29 '22 04:09

zakinster