访问类型成员

Access type member

本文关键字:成员 访问类型      更新时间:2023-10-16

在我的示例中,我有一个类Foo<T>。在我的函数test中,我需要获取Foo否则为普通类型的模板参数。首先,我开始使用std::conditional但忘记了模板参数必须全部有效,无论选择哪一个。是否为non-Foo类型创建类型专用化的唯一方法?

#include <type_traits>
template <typename TYPE>
class Foo
{
public:
  using M = TYPE;
};
template <typename T>
void test(const T& a)
{
  // actually I would have used !is_foo<T>::value for the first arg
  // but this check is fine to minimise the example
  using MY_TYPE = typename std::conditional<
    std::is_same<T, int>::value,
    T,
    typename T::M>::type; // <---Error: error: type 'int' cannot be used prior to '::' because it has no members
}
int main()
{
  test(Foo<int>()); // MY_TYPE must be int
  test(int()); // MY_TYPE must be int
  return 0;
}
好吧,

你可以做一个UnFoo助手来获得适合你的类型:

template <typename T>
struct UnFoo {
    using type = T;
};
template <typename T>
struct UnFoo<Foo<T>> {
    using type = T;
};
template <typename T>
void test(const T& a)
{
  using MY_TYPE = typename UnFoo<T>::type; //maybe with a helper to get rid of typename
}

另一种选择是为Foo<T>编写重载并将其委托给另一个函数,但这取决于您的实际test函数的作用。

你可以

做一些void_t魔法,让SFINAE想办法帮助你:

#include <type_traits>
#include <iostream>
#include <typeinfo>
template <typename TYPE>
class Foo
{
public:
  using M = TYPE;
};
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
// primary template handles types that have no nested ::T member:
template< class T, class = void_t<> >
struct M_or_T { using type = T; };
// specialization recognizes types that do have a nested ::T member:
template< class T >
struct M_or_T<T, void_t<typename T::M>> { using type = typename T::M; };

template <typename T>
void test(const T& a)
{
    using MY_TYPE = typename M_or_T<T>::type;
    std::cout << typeid(MY_TYPE).name() << "n";
}
int main()
{
  test(Foo<int>()); // MY_TYPE must be int
  test(int()); // MY_TYPE must be int
  return 0;
}

发生的情况是,M_or_T替换的第二次重载对于int(以及没有类型成员M的任何类型(失败,因此选择了第一个重载。对于具有类型成员M的类型,选择更专业的第二次重载。

#include <type_traits>
template <typename TYPE>
class Foo
{
public:
  using M = TYPE;
};
template <typename T>
void test(const Foo<T>& a)
{
    using MY_TYPE = Foo<T>::M;
    testOther<MY_TYPE>(a);
}
template <typename T>
void test(const T& a)
{
    using MY_TYPE = T;
    testOther<MY_TYPE>(a);
}
template <typename T, typename S>
void testOther(const S& a)
{
    // do stuff
}
int main()
{
  test(Foo<int>()); // MY_TYPE must be int
  test(int()); // MY_TYPE must be int
  return 0;
}

我不确定你想要什么,但我希望这就是你想要的。可能有点不对劲。我没有编译这个。