【问题标题】:c++ template type deduction : How to convert the T to const Tc++模板类型推导:如何将T转换为const T
【发布时间】: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&lt;decltype(A::str)&gt; 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

标签: c++ templates c++14


【解决方案1】:

以下作品 -

template <typename T>
const T *as_const_ptr (const T *p)
{
    return p;
}

template <
             typename T,
             typename std::enable_if_t<std::is_pointer<T>::value>* = nullptr
         >
auto __decayFunction (T t) -> decltype(as_const_ptr(t)) { return as_const_ptr(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>()));
};

【讨论】:

  • 我不确定。因此我没有接受答案:-) 我正在等待模板专家解释。当作为函数参数传递时,T 被推断为指针类型。所以 w/ char a[10], T 将是 char *,添加一个 const 以某种方式被忽略。以下也适用,其中函数签名为 T * template &lt;typename T&gt; const T* __decayFunction (const T* t) { return t; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多