Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ type trait to see if `static_cast<uint32_t>(k)` can be called on any variable of type `K`

Tags:

c++

I'm trying to write a type trait for detecting if, given a type K, I can call static_cast on variables of this type K (or reference to K) to uint32_t or not.

This is what I'm arriving at, but can't seem to make it work.

template <typename K, typename Whatever = void> struct ConvertibleToUint32 {
    static constexpr bool value = false;
};

template <typename K>
struct ConvertibleToUint32<K, decltype(static_cast<uint32_t>(std::declval<K>()))> {
    static constexpr bool value = true;
};

I have also tried using std::is_convertible, but doesn't seem to work here.

Here's a paste with a run - https://wandbox.org/permlink/iuP99PNAVIYhh208

The specialization doesn't seem to get hit.

Here's the full test program -

#include <iostream>
#include <stdint.h>

    template <typename K, typename Whatever = void> struct ConvertibleToUint32 {
        static constexpr bool value = false;
    };

    template <typename K>
    struct ConvertibleToUint32<K, decltype(static_cast<uint32_t>(std::declval<K>()))> {
        static constexpr bool value = true;
    };


struct A {
    explicit operator uint32_t() const { return 1; }
};

struct B {
};

int main()
{
    std::cout << ConvertibleToUint32<A>::value << "\n";
    std::cout << ConvertibleToUint32<B>::value << "\n";
    std::cout << std::is_convertible<A, uint32_t>::value << "\n";
}
like image 426
soumik Avatar asked Oct 22 '18 14:10

soumik


People also ask

What is a static_cast in C++?

The static_cast operator converts variable j to type float . This allows the compiler to generate a division with an answer of type float . All static_cast operators resolve at compile time and do not remove any const or volatile modifiers.

Why should you use the C++ type casting features static_cast Const_cast etc rather than the old school C variety?

It helps maintain correctness, since static_cast cannot do some casts which a C-style cast can. This helps if you make a mistake about some of the types involved, perhaps handling a pointer while being convinced it's an integer (and down several layers of templates and typedefs, that's not too difficult to imagine).

Is static cast in C?

Static casts are only available in C++. Static casts can be used to convert one type into another, but should not be used for to cast away const-ness or to cast between non-pointer and pointer types.

What is static_cast void?

static_cast<void>() is the 'C++ way' of writing void conversion. In the en.cppreference.com website mentioned as discards the value of the expression.


1 Answers

It doesen't get hit because decltype(static_cast<uint32_t>(std::declval<K>())) is not void, so it's not a more specialized version of the primary template for the argument Whatever=void.

The fix is fairly easy

template <typename K>
struct ConvertibleToUint32<K, decltype(static_cast<uint32_t>(std::declval<K>()), void())> {
    static constexpr bool value = true;
};

The second argument matches the default, and will therefore be picked up in partial ordering. Alternatively, you can just specify a default of Whatever=uint32_t and get the same effect. void is just what the general idiom employs.

template <typename K, typename Whatever = uint32_t>
struct ConvertibleToUint32 {
    static constexpr bool value = false;
};

As an aside, I suggest you start favoring the cstdint header and its std::uint32_t alias. Same net effect usually, but the use of the C++ version is generally preferable.

like image 69
StoryTeller - Unslander Monica Avatar answered Oct 17 '22 21:10

StoryTeller - Unslander Monica