【问题标题】:decltype: Access static member of class using a pointerdecltype:使用指针访问类的静态成员
【发布时间】:2020-10-02 13:13:20
【问题描述】:

我有一个模板函数f。我将它传递给一个引用或一个指向对象的指针。该对象的结构为S。我想知道S::my_tuple 的大小,它是该结构的静态成员。

当我使用std::tuple_size<decltype(T::my_tuple)>::value 通过引用传递对象时,我可以做到这一点。

如何为指针执行此操作?这目前失败了,因为my_tuple 不是S* 的成员

Play with the code.

#include <tuple>
#include <type_traits>
#include <iostream>

struct S {
  constexpr static auto my_tuple = std::make_tuple(1, 2, 3, 4);
};


template <typename T>
int f(const T object) {

  // fails if T is a pointer
  if (std::is_pointer<T>::value) {
    // error
    return std::tuple_size<decltype(T::my_tuple)>::value;
   }

    // works if T is a reference
    return std::tuple_size<decltype(T::my_tuple)>::value;
}

int main() {
    S my_struct;
    std::cout << f(my_struct); // 4, correct size of properties 
    S* my_ptr = new S;
    std::cout << f(my_ptr); // does not compile
}

编辑:

感谢您的支持。这是solution

【问题讨论】:

  • 在这种特殊情况下,您实际上并不需要分支。正如 cigien 在他的回答中所建议的那样,只需使用return std::tuple_size_v&lt;decltype(std::remove_pointer_t&lt;T&gt;::my_tuple)&gt;;。从非指针类型中删除指针不会有什么坏处。

标签: c++ pointers templates decltype


【解决方案1】:

只需使用 type trait 删除指针:

decltype(std::remove_pointer_t<std::decay_t<T>>::my_tuple)

const T object 中,T 绝不是引用。例如,如果您使用通用引用 (T&amp;&amp; object),则需要 std::decay_t&lt;T&gt;

还请注意,当您使用if 时,您的代码的所有分支都应该编译。如果要丢弃基于std::is_pointer_v&lt;T&gt; 的分支,请查看constexpr if

if constexpr (std::is_pointer_v<T>) {
    // ...
} else {
    // this code can be invalid if T is a pointer
}

有点像

if (std::is_pointer_v<T>)
    return std::tuple_size_v<decltype(std::remove_pointer_t<T>::my_tuple)>;
else
    return std::tuple_size_v<decltype(T::my_tuple)>;

一般不会起作用。

在您的特定示例中,您始终可以删除指针,因为如果T 不是指针类型,则std::remove_pointer_t&lt;T&gt; 本身就是T

template <typename T>
std::size_t f(T&&) {
    using Tuple = decltype(std::remove_pointer_t<std::decay_t<T>>::my_tuple);
    return std::tuple_size_v<Tuple>;
}

【讨论】:

  • 太棒了。你能添加一个同时使用引用和指针的版本吗?
  • @User12547645,我们也可以使用std::decay来处理引用和数组。
【解决方案2】:

您可以只使用类型特征来获取指针指向的类型,如下所示:

template <typename T>
int f(const T object) {
    return std::tuple_size_v<decltype(std::remove_pointer_t<T>::my_tuple)>;
}

这将在同一个表达式中处理引用或指针的情况。

这是demo

【讨论】:

  • 太棒了。你能添加一个同时使用引用和指针的版本吗?
  • 这个答案就是这样做的。您是否点击了演示并尝试了?
猜你喜欢
  • 2015-04-13
  • 1970-01-01
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 2014-08-07
  • 1970-01-01
  • 1970-01-01
  • 2012-09-02
相关资源
最近更新 更多