首页 > 解决方案 > decltype:使用指针访问类的静态成员

问题描述

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

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

我怎样才能为指针做到这一点?这目前失败,因为my_tuple不是S*

玩代码

#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
}

编辑:

感谢您的支持。这是解决方案

标签: c++pointerstemplatesdecltype

解决方案


只需删除具有类型特征的指针:

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

const T object,T绝不是参考。std::decay_t<T>例如,如果您使用通用引用 ( T&& object) 代替,则需要。

另请注意,当您使用if. 如果要丢弃基于 的分支std::is_pointer_v<T>,请查看constexprif

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)>;

一般不会工作。

在您的特定示例中,您始终可以删除指针,因为 ifT不是指针类型,std::remove_pointer_t<T>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>;
}

推荐阅读