gpt4 book ai didi

c++ - 确定是否传递了类型的宏

转载 作者:行者123 更新时间:2023-11-28 01:33:56 26 4
gpt4 key购买 nike

我想自己做typeid使用宏。例如如果我调用MY_TYPEID(token)我希望它解决

my_type_info<token>()如果它是一个类型,并且

my_type_info(token)如果它是一个值。

在 C++ 中有什么方法可以做到这一点吗?

最佳答案

这……很艰难。

这是完成的宏:

#define MY_TYPEID(...)                                          \
[&](auto...) { \
\
auto &&thing(__VA_ARGS__); \
auto probe = [](auto...) -> decltype(thing, void()) {}; \
\
if constexpr(detail_type_info::wizz(probe)) \
return detail_type_info::my_type_info( \
std::forward<decltype(thing)>(thing) \
); \
else \
return detail_type_info::my_type_info< \
my_decltype(__VA_ARGS__) \
>(); \
}()

这个...看起来很有趣的小发明依赖于与 this other answer of mine 相同的基本原理: thing是转发引用还是函数声明,具体取决于参数是表达式还是类型。

thing 的情况是一个引用很简单(编辑):它最终将作为转发参数到 my_type_info它将从那里拾取它。

thing 的情况是一个有趣的函数:它有一个推导的返回类型,但还没有(也不会)定义。因此,在提供定义之前不可能使用它。这种“使用”包括琐碎的使用,例如普通的 thing; : 只是试图将其放入表达式中会使程序格式错误。

这个特征是通过一层SFINAE检测到的:probe是一个通用的 lambda,其返回类型使用 thing .但是因为它是通用的,所以在我们调用 lambda 之前它实际上并没有爆炸。这正是detail_type_info::wizz尝试做:

namespace detail_type_info {
template <class F>
constexpr auto wizz(F probe) -> decltype(probe(), true) { return true; }
constexpr auto wizz(... ) -> decltype( false) { return false; }
}

detail_type_info::wizz(probe)尝试匹配这些重载之一。第一个重载尝试调用 probe在未评估的上下文中,实例化 probe (lambda)的调用运营商。如果thing实际上,在等待推断其返回类型时,这个实例化失败了,整个重载都被 SFINAE 消除了。第二个重载没有这样的事情,并且始终有效但由于 ... 而从未被优先考虑.

所以我们现在有办法通过detail_type_info::wizz(probe)来判断, 宏的参数是类型 ( false ) 还是表达式 ( true )。这是由 if constexpr 开启的,通过将最外层的 lambda 设为模板使其有效。

还有最后一关:detail_type_info::my_type_info(std::forward<decltype(thing)>(thing))true分支始终有效(即使在 thing 是函数声明的情况下实例化它会中断)。

false然而,分支不能以天真的方式被称为 return detail_type_info::my_type_info<__VA_ARGS__>() ,因为当 __VA_ARGS__ 时这会变成废话是一个不是有效非类型模板参数的表达式(例如 double ),在这种情况下,编译器会立即报错。

这就是我重用 another of my answers 的原因我在哪里实现 my_decltype ,即 decltype在表达式上和类型上的无操作,因此始终形成有效的函数调用。

所有这些机器都已到位,并增加了两个 my_type_info stub ,以下内容:

namespace detail_type_info {
template <class T>
void my_type_info(T &&) {
std::cout << __PRETTY_FUNCTION__ << '\n';
}

template <class T>
void my_type_info() {
std::cout << __PRETTY_FUNCTION__ << '\n';
}
}

int main() {
MY_TYPEID(int);
MY_TYPEID(4.2);
}

...按预期输出:

void detail_type_info::my_type_info() [with T = int]
void detail_type_info::my_type_info(T&&) [with T = double]

完整代码:

namespace detail_typeOrName {
struct probe {
template <class T>
operator T() const;
};

template <class T>
T operator * (T const &, probe);

probe operator *(probe);
}

#define my_decltype(x) decltype((x) * detail_typeOrName::probe{})

namespace detail_type_info {
template <class T>
void my_type_info(T &&) {
std::cout << __PRETTY_FUNCTION__ << '\n';
}

template <class T>
void my_type_info() {
std::cout << __PRETTY_FUNCTION__ << '\n';
}

template <class F>
constexpr auto wizz(F probe) -> decltype(probe(), true) { return true; }
constexpr auto wizz(... ) -> decltype( false) { return false; }
}

#define MY_TYPEID(...) \
[&](auto...) { \
\
auto &&thing(__VA_ARGS__); \
auto probe = [](auto...) -> decltype(thing, void()) {}; \
\
if constexpr(detail_type_info::wizz(probe)) \
return detail_type_info::my_type_info( \
std::forward<decltype(thing)>(thing) \
); \
else \
return detail_type_info::my_type_info< \
my_decltype(__VA_ARGS__) \
>(); \
}()

Live demo on Coliru

关于c++ - 确定是否传递了类型的宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50242013/

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