gpt4 book ai didi

c++ - 成员函数检测的递归type_traits

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:50:27 26 4
gpt4 key购买 nike

我正在尝试递归地应用 type_trait has_fun 以便 C 仅在 T 时启用其 fun 成员函数> 有一个。有没有办法让 C::fun 被有条件地检测到?

template <typename T>
struct has_fun {
template <class, class> class checker;
template <typename U>
static std::true_type test(checker<U, decltype(&U::fun)> *);
template <typename U>
static std::false_type test(...);
static const bool value = std::is_same<std::true_type, decltype(test<T>(nullptr))>::value;
};

struct A {
void fun(){
std::cout << "this is fun!" << std::endl;
}
};

struct B {
void not_fun(){
std::cout << "this is NOT fun!" << std::endl;
}
};

template<typename T>
struct C {
void fun() {
static_assert(has_fun<T>::value, "Not fun!");
t.fun();
}
T t;
};

int main(int argc, char const *argv[])
{

std::cout << has_fun<A>::value << std::endl;
std::cout << has_fun<B>::value << std::endl;
std::cout << has_fun<C<A>>::value << std::endl;
std::cout << has_fun<C<B>>::value << std::endl;
}

输出:

1
0
1
1

预期输出:

1
0
1
0

最佳答案

您需要允许编译器将 SFINAE 放在方法上。

模板中发生的所有检查仅考虑函数的签名,因此不会考虑您使用的 static_assert。

解决方案是在签名中添加一个检查。

凭直觉你会写

template<typename T>
struct C {
std::enable_if_t<has_fun<T>::value> fun() {
t.fun();
}

T t;
};

但这不会产生您期望的结果:编译器将拒绝编译 C,即使您不调用 C.fun();

为什么?

如果编译器可以证明它永远不会工作,则允许编译器评估代码并发出错误。因为当你声明 C 时,编译器可以证明 foo() 永远不会被允许,它会编译失败。

要解决这个问题,您可以强制该方法具有依赖类型,这样编译器就无法证明它总是会失败。

这里是技巧

template<typename T>
struct C {
template<typename Q=T, typename = if_has_fun<Q>>
void fun() {
t.fun();
}

T t;
};

编译器无法证明 Q 永远是 T,我们检查的是 Q,而不是 T,因此只有在调用 fun 时才会执行检查。

完整的工作解决方案 https://wandbox.org/permlink/X32bwCqQDb288gVl

注意:我使用的是实验中的检测器,但您可以使用您的检测器。

不过,您需要替换真正的测试,以检查是否可以正确调用该函数。

template <typename U>
static std::true_type test(checker<U, decltype(std::declval<U>().fun())> *);

参见 https://wandbox.org/permlink/MpohZzxvZdurMArP

关于c++ - 成员函数检测的递归type_traits,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47954023/

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