访问类型成员

时间:2015-10-13 15:43:22

标签: c++ c++11 template-meta-programming typetraits

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

Example

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

3 个答案:

答案 0 :(得分:5)

那么你可以制作一个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函数的作用。

答案 1 :(得分:2)

你可以做一些void_t魔术让SFINAE帮你解决问题:

M_or_T

int替换的第二次重载失败是M(对于没有类型成员M的任何类型),因此选择了第一次重载。对于具有类型成员{{1}}的类型,选择更专业的第二个重载。

答案 2 :(得分:0)

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

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