Reputation: 131
Consider somethign like the following:
template <typename T> struct Foo;
template <typename S> struct Bar
{
template <typename T> operator Foo<T>();
// ...
};
class Baz
{
Baz(Foo<int>&);
};
int main()
{
Bar<float> bar;
Baz baz(bar); // Won't work
}
I would like to use a templated operator to specify a series of possible conversions in order to avoid duplication of code/copy and paste. However, of course, now a series of conversions as on the commented line of code won't work, because in C++ the compiler reasonable won't consider all forms of the templated operators, as that would be intractable.
If I instead choose cut and paste, and define Bar as follows:
template <typename S> struct Bar
{
operator Foo<int>();
operator Foo<float>();
// many more
// ...
};
Now the chained conversion can be determined and found. What I would like is to be able to have my cake and eat it to, in particular define the operator as a template, but also provide a series of guiding declarations which can be used as if the conversion operators were defined as non-templates:
template <typename S> struct Bar
{
template <typename T> operator Foo<T>();
template operator Foo<int>(); // Not valid C++
template operator Foo<float>(); // Not valid C++
// ...
};
Is there a way to accomplish this in C++11/C++14? Does anyone have an suggestions for structuring the code which would allow be to not have replications of the definition of the conversion operator, but still have a finite set of the instantiations of the conversion operator be used as if they were individually defined?
Upvotes: 1
Views: 71
Reputation: 65600
Your problem isn't in your conversion operator declaration, it's your Baz
constructor:
Baz(Foo<int>&);
This takes a non-const reference to Foo<int>
. When you implicitly convert a Bar<S>
to a Foo<T>
, you are generating a temporary object, which can't bind to a non-const reference. If you change it to take the argument by reference-to-const, it works.
Baz(const Foo<int>&);
You can happily declare specific operators for specific types if you want:
template <typename S> struct Bar
{
template <typename T> operator Foo<T>();
operator Foo<bool>();
};
Bar<float> a{};
Foo<int> b = a; //calls operator Foo<T>
Foo<bool> c = a; //calls operator Foo<bool>
Upvotes: 1