繁体   English   中英

访问 class 成员,无论它是 function 还是数据成员

[英]accessing class member regardless of it being a function or a data member

我想为 class 成员编写通用访问器,无论它是 function 还是数据成员:

#include <type_traits>

namespace traits
{
    template <typename T, typename = void>
    struct _name;

    template <typename T>
    struct _name<T, std::void_t<decltype(std::declval<T>().name)>>
    {
        constexpr decltype(auto) operator()(const T &t) const
        {
            return t.name;
        }
    };

    template <typename T>
    struct _name<T, std::void_t<decltype(std::declval<T>().name())>>
    {
        constexpr decltype(auto) operator()(const T &t) const
        {
            return t.name();
        }
    };

    template <typename T>
    decltype(auto) name(const T &t)
    {
        return _name<T>{}(t);
    }
}

#include <string>

struct beb
{
   std::string name = "beb";
};

struct bob
{
   std::string name() const
   {
       return "bob";
   }
};

#include <iostream>

int main()
{
    std::cout << traits::name(bob());
    std::cout << traits::name(beb());
}

我正在使用具有void_t专业化的 SFINAE,但它仅适用于单一专业化。 否则会给出错误error C2953: 'traits::_name<T,void>': class template has already been defined

MSVC 最新: https://godbolt.org/z/h9WT58z8P - 不编译
GCC 12.2: https://godbolt.org/z/vc3K1M7x5 - 编译
Clang 15.0.0: https://godbolt.org/z/dqGEMfYWK - 无法编译

  1. 这段代码应该编译吗? (它只为 GCC 编译)
  2. 如何使其可编译?

_nametraits命名空间中的自定义点。 默认情况下,它使用namename()访问name 但是可以提供一种专门的使用方法,例如getName()

您似乎正在重新发明std::invoke 这个function体现了Callable概念的定义,该定义有两种特殊情况:

  • 指向数据成员的指针是“可调用的”,就像 function 将 object 作为其单个参数: std::invoke(&C::dataMember, obj)等效于obj.*dataMember
  • a pointer to member function is "callable" like a function taking the object as its first parameter: std::invoke(&C::memFun, obj, a, b, c) is equivalent to (obj.*memFun)(a, b, c)

综上所述,您的name可以简单地实现为

template <typename T>
decltype(auto) name(const T &t)
{
    return std::invoke(&T::name, t);
}

无论name是数据成员还是成员 function,它都会做正确的事情。 演示


如果您希望_name作为自定义点,只需添加一个额外的间接:使name调用_name ,而_name的默认实现调用std::invoke

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM