【发布时间】:2017-10-07 01:54:49
【问题描述】:
我需要根据结构成员的类型使用宏定义函数。
例如:
struct A {
uint32_t value; // need to define a function return uint32_t
uint8_t str[0]; // need to define a function returning const uint8_t *
};
我需要定义以下函数-
uint32_t fun () {...}
const uint8_t *fun () {...} << note the pointer types needs a const
第一次尝试:
使用 std::decay_t 将数组类型衰减为用作返回类型的指针:std::decay_t<decltype(A::str)> fun () {...}
但这不适用于上面的非标准 0 长度数组。由于政治原因,我无法更改结构的定义。所以我不得不忍受零长度数组。
第二次尝试: 推导出返回类型如下:
template<class T>
struct decay_zero { using type = std::decay_t<T>; };
template<class T>
struct decay_zero<T[]> { using type = const T *; };
template<class T, size_t N>
struct decay_zero<T[N]> { using type = const T *; }; // adding const to pointer type
template<class T>
struct decay_zero<T[0]> { using type = const T *; };
template<class T>
struct return_type {
private:
using U = typename std::remove_reference<T>::type;
public:
using type = decay_zero<U>::type;
};
return_type<decltype(A::str)>::type fun {...}
这适用于 GCC,但由于某种原因不适用于 CLANG。 CLANG 抱怨返回类型是零长度数组的数组。为什么?
第三次尝试:
所以我的第三次尝试是这样 - 声明一个“衰减”函数,如下所示。我对指针类型和非指针类型有单独的定义,以便我可以添加 指针类型的“const”
template <
typename T,
typename std::enable_if_t<std::is_pointer<T>::value>* = nullptr
>
const T __decayFunction (const T t) // making it const T
{
return return t;
}
template <
typename T,
typename std::enable_if_t<!std::is_pointer<T>::value>* = nullptr
>
decltype(auto) __decayFunction (T t)
{
return t;
}
template<class T>
struct return_type {
private:
using U = typename std::remove_reference<T>::type;
public:
using type = decltype(__decayFunction(std::declval<U>()));
};
return_type<decltype(A::str)>::type fun() { ... }
但是我看到上面函数的返回类型不是const。
如何使它成为一个常量?
【问题讨论】:
-
C++ 中不允许零大小的数组
-
我知道,但它是 GCC 和 CLANG 扩展,我必须接受它——因为它是遗留代码的一部分。
-
它是 Clang,而不是 CLANG(或 CLang)。
-
我猜它的 gcc 而不是 GCC