Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ test if lambda function

I'm making a hooking library, which basically intercepts a function and makes it jump to the intercept function.

class CHook
{
public:

    template<typename S, typename D>
    void SetupHook(S Source, D Destionation)
    {
        pSource = (PBYTE)Source;
        pDestination = (PBYTE)Destionation;
    }

private:
    PBYTE pSource;
    PBYTE pDestination;
};

I want CHook::SetupHook to take (for Destination) either DWORD (address of function), function pointer which both can be type casted to PBYTE.

I want CHook::SetupHook to also be able to take a function pointer from lambda but it cannot be type casted to PBYTE so I overload it and since I know lambda function are classes I use std::is_class to identify them.

template<typename S, typename D>
void SetupHook(S Source, typename std::enable_if<!std::is_class<D>::value, D>::type Destionation)
{
    pSource = (PBYTE)Source;
    pDestination = (PBYTE)Destionation;
}

template<typename S, typename D>
void SetupHook(S Source, typename std::enable_if<std::is_class<D>::value, D>::type Destionation)
{
    pSource = (PBYTE)Source;
    pDestination = (PBYTE)to_function_pointer(Destionation);
}

But it results in these erorrs:

error C2783: 'void CHook::SetupHook(S,std::enable_if<std::is_class<D>::value,D>::type)': could not deduce template argument for 'D'
note: see declaration of 'CHook::SetupHook'
like image 618
Budskii Avatar asked Dec 17 '25 11:12

Budskii


1 Answers

When you write code like:

template <typename S, typename D>
void SetupHook(S Source, typename std::enable_if<!std::is_class<D>::value, D>::type Destionation)
{
    // (...)
}

you make D a non-deducible type template parameter. That is, a type template parameter list, <typename S, typename D>, does not correspond to the parameter list of a function, and so, the compiler can't tell which type template parameter it is supposed to deduce in place of

typename std::enable_if<!std::is_class<D>::value, D>::type

Formally, a nested name specifier introduces a non-deduced context.

The solution is let the compiler deduce D, as a plain parameter type, and to put std::enable_if elsewhere, e.g.:

template <typename S, typename D>
typename std::enable_if<!std::is_class<D>::value>::type SetupHook(S Source, D Destionation)
{
    // (...)
}

Now, the compiler sees that D is the type of the second argument expression.

like image 87
Piotr Skotnicki Avatar answered Dec 20 '25 06:12

Piotr Skotnicki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!