获取模板参数的decltype

7

我经常想获得类模板参数的decltype,以便进一步使用它,比如在循环中。下面是我简化后的循环,展示了我的问题:

template <typename T>
class Foo {
public:
    T type; //This is my hack to get decltype of T
};

template <typename T>
class Bar {
public:

};

int main() {
    for(auto& foo : fs) {
        //Is there some way to get the decltype of the template without having to refer to some arbitrary T member of Foo?
        auto bar = someFunction<decltype(foo.type)>();
    }
}

有没有一种方法可以在不使用这种hack的情况下获取模板参数的decltype?如果没有,有什么最好的解决方法来获取这样一个值的decltype?


这只是一个包含那些对象的向量,抱歉可能可以省略它(或解释一下)。重点是我使用auto,因为我实际上是在元组上迭代,然后再迭代向量(fs),这就是为什么我真正想使用auto,然后从中提取模板类型的原因。 - Gerard
这个细节非常关键。向量是同质的。 - Lightness Races in Orbit
1
可能是重复的问题:在没有typedef的情况下,能否在模板外部访问模板参数? - Ciro Santilli OurBigBook.com
2个回答

10

您可以创建一个type_traits:

template <typename C>
struct get_template_type;

template <template <typename > class C, typename T>
struct get_template_type<C<T>>
{
    using type = T;
};

然后您使用它(假设 C = Foo<T>,您将拥有 T

typename get_template_type<C>::type

实时例子

编辑: 对于有多个模板参数的类,要检索第一个:

template <template <typename > class C, typename T, typename ... Ts>
struct get_template_type<C<T, Ts...>>
{
    using type = T;
};

谢谢,这正是我所需要的! - Gerard
对于具有默认参数或具有多个参数(例如 std::vector)的模板,此方法无法奏效。 - rubenvb
你能否提供一个在我的场景下如何使用它的示例?我原以为自己知道了,但实际上并不是很确定。 - Gerard
非常好,谢谢。最后一个请求,如果可以的话,有没有办法让这个更短一些?我能否创建一个返回typedef或其他内容的函数? - Gerard
@Gerard:为了避免使用 typename ..::type,您可以添加别名 template <typename T> using get_template_type_t = typename get_template_type<T>::type(对于 decay_t 也是如此(应该存在于 C+++14 中))。要完全删除 decay,您可以添加特化,例如 template <typename T> struct get_template_type<const T&> : get_template_type<T> {}; - Jarod42

1

标准库中的所有内容都只有类本地的typedef:

template<typename T>
struct Bla
{ using value_type = T; }

所以你可以做到:
template<typename T>
void f(const T& t)
{
  typename T::value_type some_var_with_template_type;
}

或者,您可以修改调用函数:

template<template<typename> class Class, typename T>
void f(const Class<T>& c)
{
  T some_var_with_template_type;
}

但这会对可用性和通用性造成限制。例如,如果有一个带有多个模板参数的Class,那么这将失败(尽管可以使用可变参数模板来解决这个问题)。可变参数模板版本:
template<template<typename, typename...> class Class, typename T, typename... ArgTypes>
void f(const Class<T, ArgTypes...>& t)
{
  T some_var_of_template_type;
}

请注意,value_type 的 typedef 是目前最干净、最符合习惯的解决方案。

一些代码展示了如何编写和使用这些函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接