Reputation: 1664
I am struggling to write a common interface for type conversion. I would prefer to achieve this via template specialization. My idea is to have a base template implementation to throw an exception i.e. in case no specialization is available. And user is supposed to provide every possible conversion.
I have a small implementation which of course is not working :)
#include <iostream>
#include <functional>
template <typename T, typename F>
T convert(const F & from)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
throw ( std::logic_error("Conversion not implemented!") );
}
template<>
int convert<int, std::string >( const std::string & from) {
return 1;
}
int main() {
int a;
std::string b = "hello world";
const std::string &br = b;
a = convert<decltype(a), std::remove_reference_t<std::remove_const_t<decltype(br)>> >(br);
std::cout << a << std::endl;
return 0;
}
I cant understand why the above piece of code is not working. I am removing const and reference from the br
, so it should call the implemented specialization however it does not. I am looking forward to positive replies from you and also if there is more efficient way to call the convert API without specifying the types in template parameters.
Regards, -Adnan
Upvotes: 2
Views: 128
Reputation: 6670
Just to complement, in C++20 will be possible to remove const reference with std::remove_cvref
exactly to combine std::remove_cv
and std::remove_reference
:
a = convert<decltype(a), std::remove_cvref_t<decltype(br)>>(br);
Upvotes: 0
Reputation: 66190
I am removing const and reference from the br
Yes, but in the wrong order.
You remove before const and after reference; you should remove reference before and const after
// ......................................................VVVVVVVVV reference before
a = convert<decltype(a), std::remove_const_t<std::remove_reference_t<decltype(br)>> >(br);
// ..................................^^^^^ const after
The point is that decltype(br)
is std::string const &
; I mean: const
is applied only to std::string
, not to std::string &
.
On the contrary, the reference is applied to std::string const
.
So when you apply std::remove_const
to std::string const &
, you get again std::string const &
, because the full type isn't const
.
Next you apply std::remove_reference
to std::string const &
and you get std::string const
.
So the const
remain.
If you use first std::remove_reference
, from std::string const &
you obtain std::string const
.
Then you use std::remove_const
(this time works, because the full type is const
) and you get std::string
.
Upvotes: 5