gpt4 book ai didi

c++ - 有没有办法检测一个函数是否存在并且可以在编译时使用?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:25:11 24 4
gpt4 key购买 nike

编辑: 对我的问题的简短回答是,我对 SFINAE 可以做什么有错误的看法,它根本不检查函数体:does sfinae instantiates a function body?

我有一个与此类似的问题:Is it possible to write a template to check for a function's existence?

不同的是,我不仅要检查该函数是否存在,而且我还想知道它是否真的会通过 SFINAE。这是我要完成的示例:

struct A
{
void FuncA() { std::cout << "A::FuncA" << std::endl; }
};

struct B
{
void FuncA() { std::cout << "B::FuncA" << std::endl; }
void FuncB() { std::cout << "B::FuncB" << std::endl; }
};

template<typename T>
struct Inter
{
void FuncA() { t.FuncA(); }
void FuncB() { t.FuncB(); }

T t;
};

// Always takes some sort of Inter<T>.
template<typename InterType>
struct Final
{
void CallFuncs()
{
// if( t.FuncA() exists and can be called )
t.FuncA();

// if( t.FuncB() exists and can be called )
t.FuncB();
}

InterType t;
};

void DoEverything()
{
Final<Inter<A>> finalA;
Final<Inter<B>> finalB;

finalA.CallFuncs();
finalB.CallFuncs();
}

请注意,在 CallFuncs() 中,FuncA() 和 FuncB() 将始终存在,但它们可能无法编译,具体取决于 Inter 中使用的类型 T。当我尝试在上面的链接问题中使用答案时,它似乎总是给我 true 我猜是因为它只是检查函数是否存在,而不是它实际上可以被编译(尽管我不能排除我没有搞砸什么......)

为了有条件地调用函数,我认为我可以这样使用 enable_if:

template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
i.FuncA();
}

template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
i.FuncB();
}

template<typename InterType>
struct Final
{
void CallFuncs()
{
TryCallFuncA(t);
TryCallFuncB(t);
}

InterType t;
};

但我不确定是否有任何方法可以获得 bool 值以传递给 enable_if。有什么方法可以完成这个,或者我是否需要退回到某种手动维护的类型特征来指示函数是否存在?

就可用的 C++11 功能集而言,我使用的是 MSVC 2010。

编辑:要添加一个重要说明,在我的实际情况下,类 Inter 的实现在我需要确定 Inter::FuncA/FuncB 是否会编译的地方实际上是不透明的所以我不能只是冒泡子类型并检查它们是否存在函数。

最佳答案

我现在没有时间检查这个,但是你可以添加一个专业 Final : template <typename T> struct Final< Inner<T> >; (这也有助于确保类型始终为 Inner。有了它,您可以提取用于实例化 Inter 的类型。

现在第二个问题是如何使用SFINAE检测成员函数是否存在。我相信这不应该太复杂(如果你不需要使它通用):

// Find out whether U has `void f()` member
template <typename U>
struct has_member_f {
typedef char yes;
struct no { char _[2]; };
template<typename T, void (T::*)() = &T::f>
static yes impl( T* );
static no impl(...);

enum { value = sizeof( impl( static_cast<U*>(0) ) ) == sizeof(yes) };
};

您也许可以稍微扩展它以使其更通用一些,但我认为函数的名称不能通用。当然,您可以将其编写为生成 has_member_##arg 的宏。并使用 &T:: arg .成员的类型可能更容易概括...

或者,由于我不认为这可以通用,您可以使用 has_member 中的技巧直接在您的类型中:提供两个 callFuncA重载,一个模板化了可选的第二个参数和你想要的签名,默认为 &T::FuncA转发调用,另一个带省略号的是 noop。那么callFuncs会调用callFuncAcallFuncB , SFINAE 将 dispatch 给 cargo 代理或中午,您将获得所需的行为。

template<typename T>
struct Final< Inter<T> >
{
template <typename U, void (U::*)() = &U::FuncA>
void callFuncA( Inter<T>* x ) {
x.FuncA();
}
void callFuncA(...) {}

void CallFuncs() {
callFuncA(&t); // Cannot pass nonPOD types through ...
// Similarly TryCallFuncB(t);
}
Inter<T> t;
};

关于c++ - 有没有办法检测一个函数是否存在并且可以在编译时使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10957924/

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