使用成员函数

时间:2018-01-10 12:35:29

标签: 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;

我使用的编译器版本是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;
}

4 个答案:

答案 0 :(得分:5)

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

但是,F必须是类型而不是函数名称,因此说GetBTypeFromAType不足(您需要 type )。< / p>

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

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

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

Live Demo (C++11)

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

答案 1 :(得分:1)

result_of不是你想要的。 result_of需要一个可调用的,你没有传递它。您可以直接使用decltype来简化它,即:

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

输出:

Func called with A::AA and got A::BA
Func called with A::AB and got A::BB
Func called with A::AC and got A::BC

答案 2 :(得分:1)

为什么不创建一个简单的trait类(假设你实际上不需要原始方法,但实际上只想将一种类型映射到另一种类型):

template<typename T>
struct GetBTypeFromAType;

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

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

  template <typename AType>
  void Func(AType a)
  {
    using BType = typename GetBTypeFromAType<AType>::type;
    // ...
  }
};

template<> struct GetBTypeFromAType<A::AA> { using type = A::BA; };
template<> struct GetBTypeFromAType<A::AB> { using type = A::BB; };
template<> struct GetBTypeFromAType<A::AC> { using type = A::BC; };

答案 3 :(得分:0)

我认为您应该将结果类型而不是函数名称提供给std::result_ofF(Args...) is a function type with Args... being the argument types and F being the return type.

也许你可以尝试使用它:

using BType = decltype(GetBTypeFromAType(a));

Example