Search code examples
c++templatestemplate-meta-programmingsfinae

Using SFINAE to check if member exists in class based on a template


The example here shows how we can use TMP to have the compiler elide functions based on whether a member exists for a given type. I want to write a metafunction that works for classes based on templates. Compilation should succeed if a class based on a template is provided in the function call that has the desired member.

The class:

template <typename KeyType>
struct RawBytesEntry
{
    bool used = false;
    size_t psl = 0;
    KeyType key;
    ...
}

I tried a whole slew of different suggestions and syntax permutations but I couldn't get it to work. Does anyone have any suggestions? Here is what I think is the "closest" I got:

template <template <typename> typename EntryType, typename = void>
struct has_psl : std::false_type
{
};

template <template <typename KeyType> typename EntryType>
struct has_psl<EntryType<KeyType>, std::void_t<decltype(EntryType<KeyType>::psl)>> : std::true_type
{
};

template <template <typename KeyType> typename EntryType, std::enable_if<has_psl<EntryType>::value>>
bool f(EntryType<KeyType> *buffer, size_t offset, EntryType<KeyType> *new_entry)

Solution

  • The template parameters of the template template parameter can not be used in the body.

    template <typename T, typename = void>
    struct has_psl : std::false_type
    {};
    
    template <template <typename> typename EntryType, typename KeyType>
    struct has_psl<EntryType<KeyType>, std::void_t<decltype(EntryType<KeyType>::psl)>> : std::true_type
    {};
    
    template <template <typename> typename EntryType, typename KeyType, std::enable_if<has_psl<EntryType<KeyType>>::value>>
    bool f(EntryType<KeyType> *buffer, size_t offset, EntryType<KeyType> *new_entry) {
        return true;
    }
    

    And then,

    static_assert(has_psl<int>::value == false);
    static_assert(has_psl<RawBytesEntry<int>>::value == true);
    

    Online Demo