在我附加的代码中,我正在寻找一种将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;
}
答案 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;
}
此处介绍的其他解决方案或者假设我们可以默认或聚合初始化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_of
:F(Args...) is a function type with Args... being the argument types and F being the return type.。
也许你可以尝试使用它:
using BType = decltype(GetBTypeFromAType(a));