在我附加的代码中,我正在寻找一种方法将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)
棘手的std::result_of是F(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)
这里介绍的其他解决方案要么假设我们可以默认或聚合初始化,AType要么你要求你编写一个类型特征专门化,它复制编译时已经可用的信息.