theadnangondal
theadnangondal

Reputation: 1664

Generic type conversion with template specialization

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

Answers (2)

Jo&#227;o Paulo
Jo&#227;o Paulo

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

max66
max66

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

Related Questions