声明依赖于模板函数中未知类型的变量

时间:2010-05-22 12:52:49

标签: c++ visual-c++ templates typeof

假设我正在编写一个具有类型参数T的模板函数foo。它得到一个类型为T的对象,它必须有方法bar()。在foo里面我想创建一个由bar返回的对象类型的向量。

在GNU C ++中,我可以这样写:

template<typename T>
void foo(T x) {
    std::vector<__typeof(x.bar())> v;
    v.push_back(x.bar());
    v.push_back(x.bar());
    v.push_back(x.bar());
    std::cout << v.size() << std::endl;
}

如何在Microsoft Visual C ++中执行相同的操作?有没有办法编写适用于GNU C ++和Visual C ++的代码?

6 个答案:

答案 0 :(得分:13)

您可以在标准c ++

中执行此操作
template<typename T>
struct id { typedef T type; };

template<typename T>
id<T> make_id(T) { return id<T>(); }

struct any_type {
  template<typename T>
  operator id<T>() const { return id<T>(); }
};

template<typename T, typename U>
void doit(id<T>, U& x) {
  std::vector<T> v;
  v.push_back(x.bar());
  v.push_back(x.bar());
  v.push_back(x.bar());
  std::cout << v.size() << std::endl;
}

template<typename T>
void foo(T x) {
    doit(true ? any_type() : make_id(x.bar()), x);
}

有关说明,请参阅Conditional Love

答案 1 :(得分:7)

C ++ 0x提供decltype关键字作为标准的一部分,它可以解决您的问题:

template<typename T>
void foo(T x) {
    std::vector<decltype(x.bar())> v;
    v.push_back(x.bar());
    v.push_back(x.bar());
    v.push_back(x.bar());
    std::cout << v.size() << std::endl;
}

Visual Studio 2010也支持此功能,GCC 4.3+和Comeau 4.3.9+也是如此(感谢Patrick)。

答案 2 :(得分:4)

如果您要求模板中使用的类型具有“bar”功能,您还可以要求它具有从bar返回的类型的typedef。这就是标准库通常处理此类问题的方式(例如,每个容器都有一个value_type typedef)。

class Bar1 {
public:
    typedef int bar_type;

    bar_type bar();
    ...
};

template<typename T>
void foo(T x) {
    std::vector<T::bar_type> v;
    v.push_back(x.bar());
    v.push_back(x.bar());
    v.push_back(x.bar());
    std::cout << v.size() << std::endl;
}

Bar1 b;
foo(b);

答案 3 :(得分:1)

您可以尝试Boost.Typeof,声称支持VC 8。

#include <boost/typeof/typeof.hpp>

template<typename T>
void foo(T x) {
    std::vector<BOOST_TYPEOF(x.bar())> v;
    ...

答案 4 :(得分:1)

如果将工作推迟到另一个模板函数,则可以在T :: bar上使用模板参数推导来计算出来。

// templated on the original type, and the return type of the function
template <typename T, typename mem_fn_return_type>
void doThePush (T& instance, mem_fn_return_type (T::*barptr)(void))
{
  std::vector<mem_fn_return_type> v;
  v.push_back((instance.*barptr)());
  v.push_back((instance.*barptr)());
  v.push_back((instance.*barptr)());
  std::cout << v.size() << std::endl;
}

template <typename T>
void foo(T x)
{
  doThePush(x, &T::bar);
}

但是,如果您需要在多个地方使用该类型,则最好在其他答案中使用这些技术。

答案 5 :(得分:0)

如果您使用的是Visual C ++ 10,它们支持“decltype”运算符,它将返回给定表达式的类型。