gpt4 book ai didi

c++ - 消除函数指针和指向类实例的指针之间的歧义

转载 作者:行者123 更新时间:2023-11-30 03:45:37 25 4
gpt4 key购买 nike

我有一个实用程序可以执行 static_assert 是否可以使用给定的参数列表调用函数

我有 2 个重载:

对于 lambda 和自由函数:

template<typename Func, typename... Args>
void assert_is_callable(Func&&, Args&&...)

成员函数:

template<typename Class, typename MemFunc, typename... Args>
void assert_is_callable(Class*, MemFunc, Args&&...)

我遇到的问题是,当我用自由函数调用 assert_is_callable 时,选择了第二个重载;函数指针推导为 Class,第一个参数推导为 MemFunc,其余参数推导为 Args...

void func(int, double, char) {  }

assert_is_callable(func, 1, 2.3, 'c'); // selects the member_function version

编译错误输出:

In instantiation of 'void assert_is_callable(Class*, MemFunc, Args&& ...) [with Class = void(int, double, char); MemFunc = int; Args = {double, char}]':
prog.cpp:79:41: required from here
prog.cpp:51:5: error: static assertion failed: the provided type is not callable with the supplied arguments
static_assert(is_callable_member_function<Class, MemFunc, Args...>::value,
^

问题:

在将 assert_is_callable 与自由函数一起使用时,如何防止选择成员函数重载?

示例:

working example on ideone

#include <tuple>
#include <type_traits>
#include <functional>

// functor

template<class Func, class... Args>
class is_callable
{
using yes = char(&)[2];
using no = char(&)[1];

template<class F>
static yes check(decltype(std::declval<F&>()(std::declval<Args>()...))*);

template<class F>
static no check(...);
public:
enum { value = (sizeof(check<Func>(nullptr)) == sizeof(yes)) };
};

// member function

template<typename Class, typename MemFunc, class... Args>
class is_callable_member_function
{
using yes = char(&)[2];
using no = char(&)[1];

template<class C, class MF>
static yes check(decltype((std::declval<C>().*std::declval<MF>())(std::declval<Args>()...))*);

template<class C, class MF>
static no check(...);
public:
enum { value = (sizeof(check<Class, MemFunc>(nullptr)) == sizeof(yes)) };
};

//////////////////////////////////

template<typename Func, typename... Args>
void assert_is_callable(Func&&, Args&&...)
{
static_assert(is_callable<Func, Args...>::value,
"the provided type is not callable with the supplied arguments");
}

template<typename Class, typename MemFunc, typename... Args>
void assert_is_callable(Class*, MemFunc, Args&&...)
{
static_assert(is_callable_member_function<Class, MemFunc, Args...>::value,
"the provided type is not callable with the supplied arguments");
}

//////////////////////////////////

struct Foo
{
void func(int, double, char)
{
}
};

void func(int, double, char)
{
}

int main()
{
// member function
Foo f;
assert_is_callable(&f, &Foo::func, 1, 2.3, 'c');

// lambda
auto lambda = [](int, double, char) { };
assert_is_callable(lambda, 1, 2.3, 'c');

// free function
// assert_is_callable(func, 1, 2.3, 'c'); // selects the member_function version

return 0;
}

最佳答案

可以使用SFINAE,也可以直接使用强类型:

template<typename Class, typename C, typename MemFunc, typename... Args>
std::enable_if_t<std::is_class<Class>::value>
assert_is_callable(Class*, MemFunc (C::*), Args&&...)
{
static_assert(is_callable_member_function<Class, MemFunc (C::*), Args...>::value,
"the provided type is not callable with the supplied arguments");
}

Demo

关于c++ - 消除函数指针和指向类实例的指针之间的歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34682765/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com