gpt4 book ai didi

c++ - 如何确定一个类型是否可以仅使用 const 引用调用?

转载 作者:可可西里 更新时间:2023-11-01 15:39:16 25 4
gpt4 key购买 nike

我想写一个 C++ 元函数 is_callable<F, Arg>定义 value成为true ,当且仅当类型 F 具有 SomeReturnType operator()(const Arg &) 形式的函数调用运算符时.例如,在下面的情况下

struct foo {
void operator(const int &) {}
};

我要is_callable<foo, int &>成为falseis_callable<foo, const int &>成为true .这是我到目前为止所拥有的:

#include <memory>
#include <iostream>

template<typename F, typename Arg>
struct is_callable {
private:

template<typename>
static char (&test(...))[2];

template<unsigned>
struct helper {
typedef void *type;
};

template<typename UVisitor>
static char test(
typename helper<
sizeof(std::declval<UVisitor>()(std::declval<Arg>()), 0)
>::type
);
public:
static const bool value = (sizeof(test<F>(0)) == sizeof(char));
};

struct foo {
void operator()(const int &) {}
};

using namespace std;

int main(void)
{
cout << is_callable<foo, int &>::value << "\n";
cout << is_callable<foo, const int &>::value << "\n";

return 0;
}

这会打印出 11 , 但我想要 01因为foo只定义 void operator()(const int &) .

最佳答案

经过几个小时的游玩和一些serious discussions in the C++ chat room ,我们终于得到了一个版本,它适用于可能重载或继承的 operator() 和函数指针,基于@KerrekSB 和@BenVoigt 的版本。

#include <utility>
#include <type_traits>

template <typename F, typename... Args>
class Callable{
static int tester[1];
typedef char yes;
typedef yes (&no)[2];

template <typename G, typename... Brgs, typename C>
static typename std::enable_if<!std::is_same<G,C>::value, char>::type
sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...));

template <typename G, typename... Brgs, typename C>
static typename std::enable_if<!std::is_same<G,C>::value, char>::type
sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...) const);

template <typename G, typename... Brgs>
static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...));

template <typename G, typename... Brgs>
static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...) const);

template <typename G, typename... Brgs>
static yes test(int (&a)[sizeof(sfinae<G,Brgs...>(&G::operator()))]);

template <typename G, typename... Brgs>
static no test(...);

public:
static bool const value = sizeof(test<F, Args...>(tester)) == sizeof(yes);
};

template<class R, class... Args>
struct Helper{ R operator()(Args...); };

template<typename R, typename... FArgs, typename... Args>
class Callable<R(*)(FArgs...), Args...>
: public Callable<Helper<R, FArgs...>, Args...>{};

Live example on Ideone .请注意,这两个失败的测试是重载的 operator() 测试。这是 GCC 的可变参数模板错误,已在 GCC 4.7 中修复。 Clang 3.1 还将所有测试报告为已通过

如果你想让带有默认参数的 operator() 失败,有一种可能的方法可以做到这一点,但是其他一些测试会在那个时候开始失败,我发现它太麻烦了尝试改正。

编辑:正如@Johannes 在评论中正确指出的那样,我们在这里有一点不一致,即 functors which define a conversion to function pointer不会被检测为“可调用”。恕我直言,修复起来非常重要,因此我不会为它烦恼(现在)。如果您绝对需要此特性,那么请发表评论,我会看看我能做些什么。


既然已经说了这一切,恕我直言,这个特性的想法是愚蠢的。为什么您会有这样确切的要求?为什么标准 is_callable 不够用?

(是的,我认为这个想法很愚蠢。是的,我仍然去 build 这个。是的,它很有趣,非常有趣。不,我没有疯。至少我是这么认为的......)

关于c++ - 如何确定一个类型是否可以仅使用 const 引用调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8903959/

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