简体   繁体   English

部分专门化lambda的类模板

[英]Partially specialize class template by lambda

I have template type that store information about function or member function (like return type, number or parameters and so on). 我有模板类型,存储有关函数或成员函数的信息(如返回类型,数字或参数等)。

template<class R, class... FuncParams>
struct SFuncInfo
{
    using Signature = R(FuncParams...);
    using Ret = R;

    static constexpr size_t numParams = sizeof...(FuncParams);
};

// member
template<class T, class Ret, class... Params>
struct SFuncInfo<Ret(T::*)(Params...)> : SFuncInfo<Ret, Params...> 
{
    static constexpr bool isMemberFunction = true;
};

// function
template<class R, class... FuncParams>
struct SFuncInfo<R(FuncParams...)> : SFuncInfo<R, FuncParams...> 
{
    static constexpr bool isMemberFunction = false;
};

This is how it can be used: 这是它的使用方法:

int func(const char* str) { return 1; }

struct MyType
{
    bool memFunc(int val, float fl) { return true; }
};

int main() 
{
    static_assert(!SFuncInfo<decltype(func)>::isMemberFunction, "");
    static_assert(std::is_same<SFuncInfo<decltype(func)>::Ret, int>::value, "");

    static_assert(SFuncInfo<decltype(&MyType::memFunc)>::isMemberFunction, "");
    static_assert(std::is_same<SFuncInfo<decltype(&MyType::memFunc)>::Ret, bool>::value, "");
}

This code compiles. 这段代码编译。 But I want also to handle cases with lambdas. 但我也希望用lambdas处理案例。 Something like this: 像这样的东西:

auto lambda = [](int, bool) -> float { return 3.14f; };

static_assert(SFuncInfo<decltype(lambda)>::isMemberFunction, "");
static_assert(std::is_same<SFuncInfo<decltype(lambda)>::Ret, float>::value, "");

I tried different option. 我尝试了不同的选择。 Few of the are listed below. 下面列出的很少。

template<class T>
struct SFuncInfo<T, decltype(T())>
{
    static constexpr bool isMemberFunction = true;
};

template<class T>
struct SFuncInfo<T, decltype(&std::decay<decltype(std::declval<T>())>::type::operator())>
{
    static constexpr bool isMemberFunction = true;
};

It doesn't resolve to any of these specialization. 它没有解决任何这些专业化。

By the way, the code below also compiles: 顺便说一句,下面的代码也编译:

auto lambda = [](int, bool) -> float { return 3.14f; };

using LambdaType = std::decay<decltype(std::declval<decltype(lambda)>())>::type;
using CallOperator = decltype(&LambdaType::operator());
static_assert(std::is_same<SFuncInfo<CallOperator>::Ret, float>::value, "");
static_assert(SFuncInfo<CallOperator>::isMemberFunction, "");

Here is LIVE DEMO is someone wants to play around. 这里的LIVE DEMO是有人想玩的。

Does anyone has a good solution for this? 有没有人有这个很好的解决方案?

Adding this single partial specialization works on my side: 添加这个单一的部分专业化在我身边起作用:

template<class Lambda>
struct SFuncInfo<Lambda> : SFuncInfo<decltype(&Lambda::operator())> { };

The solution would be to make an overload that is only available to callable object types and inherit from SFuncInfo with the operator() type. 解决方案是进行仅对可调用对象类型可用的重载,并使用operator()类型从SFuncInfo继承。

template<typename T>
struct SFuncInfo<T, decltype(void(&T::operator()))> : SFuncInfo<decltype(&T::operator())> {};
//     constraint ----------------^

However to support this I separated the specializations and the metadata classes, splitting them into SFuncInfo and SFuncInfoBase : 但是为了支持这一点,我将特化和元数据类分开,将它们分成SFuncInfoSFuncInfoBase

template<class R, class... FuncParams>
struct SFuncInfoBase
{
    using Signature = R(FuncParams...);
    using Ret = R;

    static constexpr size_t numParams = sizeof...(FuncParams);
};

template<class T, typename = void>
struct SFuncInfo;

// member
template<class T, class Ret, class... Params>
struct SFuncInfo<Ret(T::*)(Params...)const> : SFuncInfo<Ret(T::*)(Params...)> {};

template<class T, class Ret, class... Params>
struct SFuncInfo<Ret(T::*)(Params...)> : SFuncInfoBase<Ret, Params...> 
{
    static constexpr bool isMemberFunction = true;
};

Live example 实例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM