Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there a way to get the type of a dereferenced value from a dereference-able type?

I’m playing around with C++ concepts and came across an interesting problem. I have the following two custom-defined concepts:

template<typename T>
concept is_dereferencable = requires (T t) { *t; };

template<typename T>
concept is_printable = requires (T t) { std::cout << t; };

As the names suggest, the first one is used to determine if a given type can be dereferenced, while the other one to check if a type supports output operator. I also have a function template called println, which looks like this:

template<typename T>
void println(const T& t)
{
    if constexpr (is_dereferencable<T>) {
        if constexpr (is_printable<decltype(*t)>) {
            std::cout << *t << '\n';
        }
    } else if constexpr (is_printable<T>) {
        std::cout << t << '\n';
    }
}

This prints the dereferenced value *t if and only if type T is dereference-able and the type of the dereferenced value is printable. So, for example, I can use this function template with something like an std::optional:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

int main
{
    std::optional<std::string> stringOpt {"My Optional String"};
    ::println(stringOpt);

    return 0;
}

This will print My Optional String as expected. While this is nice, the function will just silently print nothing if the type of a dereferenced value of a derefernce-able is not printable. So, for a user-defined type Person, the following will just print nothing:

struct Person
{
    std::string m_name;
    explicit Person(const std::string& name) : m_name {name} {}
};

int main
{
    std::optional<Person> personOpt {"John Doe"}
    ::println(personOpt);
    return 0;
}

So I would like to move the above compile-time ifs to a requires clause itself in order to get compile time errors in such cases. Is there a way to achieve that? Is there a way to get the dereferenced type of a given template type T? To make it a bit clearer, I would like to have something like this:

template<typename T>
requires is_dereferencable<T> && is_printable<decltype(*T)>
void printDereferencable(const T& t)
{
    std::cout << *t << '\n';
}

P.S.: I understand that I could remove the nested if and just fail upon trying to call an output operator on something that doesn’t support it. However, I want to specifically move this compile-time error to the concept to get a clearer error message.

>Solution :

you can use std::declval

template<typename T>
requires is_dereferencable<T> && is_printable<decltype(*std::declval<T>())>
void printDereferencable(const T& t)
{
    std::cout << *t << '\n';
}

or you can just write a is_dereference_printable concept

template<typename T>
concept is_dereference_printable = requires (T t) { std::cout << *t; };
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading