我要求一个模板技巧来检测一个类是否具有给定签名的特定成员函数.
问题类似于这里引用的问题 http://www.gotw.ca/gotw/071.htm 但不一样:在Sutter的书中,他回答了C类必须提供成员函数的问题.一个特定的签名,否则程序将无法编译.在我的问题中,我需要做一些事情,如果一个类有这个功能,否则做"其他".
boost :: serialization面临类似的问题,但我不喜欢他们采用的解决方案:模板函数默认调用具有特定签名的自由函数(您必须定义),除非您定义特定的成员函数(在他们的情况下"序列化",它采用给定类型的2个参数)与特定签名,否则将发生编译错误.那就是实现侵入式和非侵入式序列化.
我不喜欢这个解决方案有两个原因:
我需要为没有该成员函数的类定义自定义行为,并且我的实体位于不同的名称空间内(我不想覆盖在一个名称空间中定义的全局函数,而我在另一个名称空间中)
你能给我一个解决这个难题的提示吗?
给定void *
一些存储,如何检查它是否指向正确对齐的存储而没有任何实现定义的行为?
我们当然有std::align
,但是有更有效的方法吗?
template <std::size_t alignment>
inline bool is_aligned(void * ptr) noexcept {
std::size_t max = 1u;
return std::align(alignment, 1u, ptr, max);
}
Run Code Online (Sandbox Code Playgroud)
PS:我需要以兼容C++标准的方式执行此操作,而不依赖于任何特定于平台的(实现定义的)黑客攻击.
PPS:我为我(理解)英语而道歉,而不是我的母语.
EDIT(2018.08.24):从标题中删除了"有效",添加了更多的措辞,强调我不希望任何实现定义或特定于平台的行为.
I'm trying to get this is-class-defined-check to work, which relies on the fact that decltype(std::declval<Foo>().~Foo())
is void
if Foo
has a destructor (which it has if it is defined…) and is ill-formed otherwise, invoking SFINAE in this case.
However, I can't get the code to work with GCC 9.1, and that is because GCC 9.1 seems to consider that type to be void &
if the destructor is defaulted, consider this example:
#include <type_traits>
class Foo {
public:
// …
Run Code Online (Sandbox Code Playgroud) 从 C++20 开始,我们可以有:
constexpr bool is_little_endian = std::endian::native == std::endian::little;
Run Code Online (Sandbox Code Playgroud)
如果可用,我希望有执行此操作的代码,否则执行运行时检测。这可能吗?
也许代码看起来像:
template<bool b = std_endian_exists_v> constexpr bool is_little_endian;
template<> constexpr bool is_little_endian<true> = std::endian::native == std::endian::little;
template<> constexpr bool is_little_endian<false> = runtime_detection();
Run Code Online (Sandbox Code Playgroud)
我知道__cplusplus
通过预处理器进行测试是可能的,但是 C++20 中的编译器阶段在各个阶段都支持,因此这在任一方向都不是可靠的指标。
我需要一个可以这样调用的模板:
int x = type_exists< std::vector<int> >::value;
Run Code Online (Sandbox Code Playgroud)
如果#include <vector>
在源中较早存在(显式或传递),则应将x设置为1 ,否则应将x设置为0.
是否可以在C++中完成?我正在使用GCC,所以GCC扩展也很好.
也可以稍微改变调用语法.
运行C++编译器两次是不行的:首先只是弄清楚我们是否收到编译错误.
假设我有以下代码:
// exposition-only, I can't use this macro in my solution
#if defined(HAS_MY_ENUM)
enum my_enum {
zero,
one,
};
#endif
enum empty {
placeholder, // an enum must always have a value
};
Run Code Online (Sandbox Code Playgroud)
我希望有一个条件类型别名my_enum_or_empty
,如果已定义,则设置为my_enum
,否则设置为empty
,例如:
using my_enum_or_empty = std::conditional<my_enum_exists, my_enum, empty>;
Run Code Online (Sandbox Code Playgroud)
我想要一个基于 SFINAE 的解决方案,它可以为我提供my_enum_exists
.
我正在考虑这种方法,但它需要 的前向声明my_enum
,并且不能前向声明,因为它是无大小的。我无法添加尺寸,因为它enum
来自外部库。你有什么想法?
我的用例是,这my_enum
是在我无法控制的外部 C 库中定义的。我需要针对该库的两个版本(带my_enum
和不带)编译我的代码。定义的标头源my_enum
不能更改,即它必须是旧的 C 样式enum
。
编译时不知道库版本。可惜没有LIBRARY_VERSION
宏。我只需要依靠这一点 …