使用成员函数时,使用std :: result_of进行编译失败

e27*_*314 2 c++ c++11

在我附加的代码中,我正在寻找一种方法将1种类型映射到另一种类型.代码无法使用错误进行编译

[root@]# g++ -std=c++11 test.cpp -o test; ./test
test.cpp: In member function ‘void A::Func(AType)’:
test.cpp:32:58: error: template argument 1 is invalid
     using BType = std::result_of<GetBTypeFromAType(AType)>::type;
Run Code Online (Sandbox Code Playgroud)

我正在使用的编译器版本是5.3.1,任何想法如何解决?

#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
#include <memory>

template <class T>
std::string GetTypeName()
{
  //http://stackoverflow.com/questions/23266391/find-out-the-type-of-auto/23266701#23266701
  std::unique_ptr<char, void(*)(void*)> name{abi::__cxa_demangle(typeid(T).name(), 0, 0, nullptr), std::free};
  return name.get();
}


struct A
{
  struct AA {};
  struct AB {};
  struct AC {};

  struct BA {};
  struct BB {};
  struct BC {};

  BA GetBTypeFromAType(AA a) { return BA(); }
  BB GetBTypeFromAType(AB a) { return BB(); }
  BC GetBTypeFromAType(AC a) { return BC(); }

  template <typename AType>
  void Func(AType a)
  {
    using BType = std::result_of<GetBTypeFromAType(AType)>::type;
    std::cout << "Func called with " << GetTypeName<AType>() << " and got " << GetTypeName<BType>() << std::endl;
  }
};

int main()
{
  A a;
  A::AA aa;
  A::AB ab;
  A::AC ac;
  a.Func(aa);
  a.Func(ab);
  a.Func(ac);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

And*_*dyG 5

棘手的std::result_ofF(Args...)语法是误导性的.因为它看起来像一个函数,所以你很想把它称为函数.(我认为这种不稳定的语法是其在C++中被弃用的部分原因17)

但是,F必须是一个类型而不是函数名称,所以说GetBTypeFromAType不够(你需要它的类型).

但是,由于它过载,你不能简单地把它包装成decltype; 你需要转换到适当的重载来获得一个正确的指针,这会破坏整个目的(因为如果你知道它会调用哪个重载你就不需要首先要求返回类型)

std::result_of最好与函数对象一起使用,因此最简单的解决方法是将调用包装GetBTypeFromAType在lambda中,然后decltype在该lambda上使用:

template <typename AType>
void Func(AType a)
{
  auto wrapper = [this](AType&& a){return GetBTypeFromAType(std::forward<decltype(a)>(a));};
  using BType = typename std::result_of<decltype(wrapper)(AType)>::type;
  std::cout << "Func called with " << GetTypeName<AType>() << " and got " << GetTypeName<BType>() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

现场演示(C++ 11)

这里介绍的其他解决方案要么假设我们可以默认或聚合初始化,AType要么你要求你编写一个类型特征专门化,它复制编译时已经可用的信息.