std::void_t 与 SFINAE 用法中的自定义函数

问题描述 投票:0回答:1
#include <iostream>



template <typename T>
struct CheckX
{
    using TypeOfX = decltype(T::x);
    using Value = void;
};


struct A
{

};

struct B
{
    int x;
};

template <typename T , typename = void>
struct Res
{
    static constexpr bool value = false;
};

// template <typename T>
// struct Res<T , std::void_t<decltype(T::x)>>
// {
//     static constexpr bool value = true;
// };

template <typename T>
struct Res<T , typename CheckX<T>::Value>
{
    static constexpr bool value = true;
};


int main()
{
    std::cout << Res<B>::value << '\n'; 
    std::cout << Res<A>::value << '\n'; 
}

这些是我想要实现一个检查器的代码,该检查器检查结构中是否存在成员

x
。我注意到使用自定义
CheckX
会导致编译失败,而 std 库
std::void_t
会完成这项工作。我在这里缺少什么?

c++ template-meta-programming sfinae
1个回答
0
投票

第一个版本(带有

void_t
)完全按照您的预期工作:
对于类
A
,当考虑此
std::void_t<decltype(T::x)>
时,
A::x
会导致替换失败(由于缺少
Res
)。
这是经典的 SFINAE。
因此,这个版本的
Res
被丢弃,留下默认的
Res
value = false

第二个版本(带有

CheckX<T>
)甚至没有进入SFINAE阶段
Res

为了检查
CheckX<T>::Value
,首先将
CheckX<T>
实例化。作为其中的一部分,
using TypeOfX = decltype(T::x)
被解析,并且由于
A
不包含
x
decltype(T::x)
会触发错误。
解析
using
的这个
A
声明不是
Res
的 SFINAE 的一部分(它是在初步阶段完成的)。

注意,这种场景正是

std::void_t
的确切目的:

将任何类型的序列映射到该类型的实用程序元函数 空白。 此元函数是利用 SFINAE 先验的便捷方法 C++20 的概念,特别是有条件删除 根据表达式是否为候选集的函数 在未评估的上下文中有效(例如 decltype 的操作数 表达式),允许存在单独的函数重载或 基于支持的操作的专业化。

(重点是我的)

另请参阅

cppreference.com 页面中的 
struct has_type_member 示例

© www.soinside.com 2019 - 2024. All rights reserved.