std::d eclare_if 或其他在编译时丢弃成员声明的假设方法
std::declare_if or other hypothetical ways for discarding member declarations at compile time
SFINAE对于丢弃函数体非常有用,但是为什么它不能用于丢弃成员变量呢?
是否计划在某个时候将此类功能添加到现代C++中?我尝试使用std::enable_if
,std::conditional
(如果允许它具有零大小的类型,这将起作用,但可能会破坏其他所有内容(。
我希望能够使用假设的 SFINAE 模式生成别名,例如:
template<class T, SIZE>
struct Vector {
union {
T mArray[SIZE] = {};
struct {
std::declare_if<SIZE >= 1, T>::type x;
std::declare_if<SIZE >= 2, T>::type y;
std::declare_if<SIZE >= 3, T>::type z;
};
};
};
除了缺乏编译器支持之外,我认为目前不存在任何充分的理由?如果您对优雅的解决方法或解决方案有任何想法,而无需向联合添加额外的大小,或编写样板代码(例如基本代码(,然后进行部分专门的派生。我很想知道。
借助
c++20 属性 [[no_unique_address]]
,哪:
指示此数据成员不需要具有与其类的所有其他非静态数据成员不同的地址。这意味着,如果成员具有空类型(例如无状态分配器(,编译器可以对其进行优化以不占用空间。
应用于您的用例:
#include <type_traits>
template <typename T, int SIZE>
struct Vector
{
T x;
[[no_unique_address]] std::conditional_t<(SIZE > 1), T, decltype([]{})> y;
[[no_unique_address]] std::conditional_t<(SIZE > 2), T, decltype([]{})> z;
};
int main()
{
static_assert(sizeof(Vector<double, 1>) == 1 * sizeof(double));
static_assert(sizeof(Vector<double, 2>) == 2 * sizeof(double));
static_assert(sizeof(Vector<double, 3>) == 3 * sizeof(double));
}
在这里,我将decltype([]{})
用作空类型,产生不同的类型,以便它们可以共享相同的地址。
现在是不可能的,但你可以编写一个接受整数值的模板化get()
函数。此外,如果您使用的是 C++ 17,您也可以使用结构化绑定。
#include <tuple>
#include <iostream>
// not elegant way of naming as enum will polute the whole namespace where it is defined
enum Idx {
X = 0,
Y = 1,
Z = 2,
W = 3,
R = 0,
G = 1,
B = 2,
A = 3
};
template <typename T, std::size_t SIZE>
struct Vector
{
template<std::size_t Index>
T& get() {
static_assert(Index < SIZE, "Invalid Index");
return data[Index];
}
template<std::size_t Index>
const T& get() const noexcept {
static_assert(Index < SIZE, "Invalid Index");
return data[Index];
}
T data[SIZE];
};
//only needed if structured binding is required
namespace std {
template<typename T, size_t SIZE>
struct tuple_size<Vector<T, SIZE>> {
constexpr static size_t value = SIZE;
};
template<typename T, size_t I, size_t SIZE>
struct tuple_element<I, Vector<T, SIZE>> {
using type = T;
};
}
int main()
{
Vector<int, 2> value = {0, 1};
std::cout << "x = " << value.get<X>() << ": y = " << value.get<Y>() << 'n';
// structured binding, available only in C++17
auto& [x, y] = value;
std::cout << "x = " << x << ": y = " << y << 'n';
// will generate a compiler error
//auto& [x1, y1, z1] = value;
// will invoke the static assert
//auto z = value.get<Z>();
return 0;
}
相关文章:
- 使用静态成员声明类时遇到问题
- 错误 C2059:语法错误:从结构成员声明'constant'
- std::d eclare_if 或其他在编译时丢弃成员声明的假设方法
- C++ 成员声明中不允许使用限定名称
- 又一个"未找到成员声明"
- auto f = bind(dist<>,gen) 在成员声明C++失败。未被识别为函数
- C++错误:成员声明末尾的预期“;”
- 静态成员声明 c++11
- 如何将成员声明为指向外部"C"函数的指针?
- C++11 - 将非静态数据成员声明为 'auto'
- 类成员声明的快捷方式
- libclang 获取成员声明
- 将成员声明与enable_if一起使用
- 找不到成员声明
- C++错误:找不到成员声明
- 找不到c++成员声明
- 成员声明顺序在类中如果彼此依赖,则为最优解
- 将struct的成员声明为uint32_t时额外的字节
- 为什么类的大小取决于成员声明的顺序?以及如何
- 是成员声明`decltype(name)name;`在第一个名称引用封闭作用域的本地结构中允许