Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't use sizeof for T if T is a function

I have near following struct for detecting if type can be passed by value:

template <class T>
struct should_be_passed_by_value {
    static constexpr bool value = 
        std::is_scalar<T>::value || 
        std::is_array<T>::value || 
        std::is_reference<T>::value || 
        (sizeof(T) <= sizeof(void*));
};

Problem is: when I instantiate it for C-like function pointer or std::function, the compiler says:

invalid application of 'sizeof' to a function type

(of course).

How can it be modified so that value will contain false?

like image 751
vladon Avatar asked Jan 05 '17 17:01

vladon


1 Answers

How can it be modified so that value will contain false?

Any problem can be solved with an extra layer of indirection. We have some of these built in already. Basically, you want your smallness check to only be used when T is not a function. There's a metafunction for that already: std::conditional. We can use it to delay evaluation.

The smallness check, we separate out into its own metafunction:

template <class T>
struct is_small
    : std::integral_constant<bool, (sizeof(T) <= sizeof(void*))>
{ };

And then we can rewrite your condition as:

template <class T>
struct should_be_passed_by_value {
    static constexpr bool value = 
        std::is_scalar<T>::value || 
        std::is_array<T>::value || 
        std::is_reference<T>::value || 
        std::conditional_t<
            std::is_function<T>::value,
            std::false_type,
            is_small<T>>::value;
};

This way, is_small<T> is only instantiated if T is not a function.

like image 150
Barry Avatar answered Oct 05 '22 10:10

Barry