gpt4 book ai didi

c++ - 无法为函数指针专门化函数

转载 作者:搜寻专家 更新时间:2023-10-31 00:28:02 24 4
gpt4 key购买 nike

我正在使用 VS2015 更新 3。我有一个函数,我希望根据可调用对象的返回类型来专门化。当可调用对象是仿函数时,一切都按预期进行。当可调用对象是函数或函数指针时,它无法特化重载函数。我觉得我错过了一些明显的东西,但我已经一年多没有对 SFINAE 做过任何事情了。

我错过了什么导致特化失败?

template <typename T>
struct S
{
T mOp;
template <typename = void>
typename std::enable_if<
std::is_same<
std::remove_cv_t<
std::remove_reference_t<
decltype(mOp())
>
>,
void
>::value
>::type func()
{
std::cout << "bool" << std::endl;
}
template <typename = void>
typename std::enable_if<
std::is_same<
std::remove_cv_t<
std::remove_reference_t<
decltype(mOp())
>
>,
bool
>::value
>::type func()
{
std::cout << "void" << std::endl;
}
};

template <typename T>
auto createS(T&& t)
{
return S<T>{ t };
}

void vfunc()
{
}
bool bfunc()
{
return true;
}
struct vfunctor
{
void operator()()
{
}
};
struct bfunctor
{
bool operator()()
{
return true;
}
};

void func()
{
createS(bfunc).func(); // Fails to specialize func()
createS(vfunc).func(); // Fails to specialize func()
createS(vfunctor{}).func();
createS(bfunctor{}).func();
}

最佳答案

这些都不起作用,因为替换失败只是替换的直接上下文中的失败 - 而您正在尝试在不依赖于直接函数模板参数的上下文中执行 SFINAE。 func() 中的约束基于 class 模板参数,而不是本地函数模板参数,因此这些只是一个硬错误。

最简单的方法是通过标记分派(dispatch)。将 decltype(mOp()) 包装到标记类型中,然后重载:

template <class T> struct tag { };

template <typename T>
struct S
{
T mOp;

void func() {
func_impl(tag<std::decay_t<decltype(mOp())>>{});
}

void func_impl(tag<bool> ) { std::cout << "bool\n"; }
void func_impl(tag<void> ) { std::cout << "void\n"; }
};

如果您出于某种原因需要 func() 本身对 SFINAE 友好,那么您可以引入一个新的模板参数来伪造原始参数:

template <class..., class U=T>
auto func()
-> decltype(func_impl(tag<std::decay_t<std::invoke_result_t<U>>>{}))
{
return func_impl(tag<std::decay_t<std::invoke_result_t<U>>>{});
}

请注意,这必须出现在各种 func_impl 重载的声明之后

关于c++ - 无法为函数指针专门化函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46838311/

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