我正在尝试使用friend重载模板结构中的函数。
我想用它来将类型映射到另一种类型。在下面的代码中,我想将int
类型映射到MyType
。
这是我到目前为止所做的:
void map(...){} // Worst case
// Here's the class that will overload our function
template<typename Type, typename T>
struct MakeFunction {
friend Type map(T) { return {}; }
};
// Make the function with int?
struct MyType : MakeFunction<MyType, int> {};
int main() {
// The type obtained is void, worst case choosed. The expected result is `MyType` as return type.
std::cout << typeid(decltype(map(int{}))).name() << std::endl;
return 0;
}
然后,我试过了:
template<typename T>
void map(){} // Worst case
// Here's the class that will overload our function
template<typename Type, typename T>
struct MakeFunction {
// Compilation error.
friend Type map<T>() { return {}; }
};
struct MyType : MakeFunction<MyType, int> {};
int main() {
std::cout << typeid(decltype(map<int>())).name() << std::endl;
return 0;
}
但编译失败了:
error: defining explicit specialization ’map<T>’ in friend delcaration
如何更改声明以便选择正确的功能?或者有没有办法在不使用样板的情况下映射类型?
答案 0 :(得分:3)
下面的代码展示了如何定义满足您需求的宏DEFINE_TYPE_MAPPING
(这在某种程度上是一个展示该想法的草图):
#include <iostream>
#include <typeinfo>
void map(...){} // Worst case
template<class T> struct TypeMapping;
template<class T>
typename TypeMapping<T>::type map(const T&);
#define DEFINE_TYPE_MAPPING(T, U) \
template<> struct TypeMapping<T> { typedef U type; };
struct MyType {};
DEFINE_TYPE_MAPPING(int, MyType);
DEFINE_TYPE_MAPPING(char, float*);
DEFINE_TYPE_MAPPING(std::ostream, unsigned long);
int main() {
std::cout << typeid(decltype(map(int{}))).name() << std::endl;
std::cout << typeid(decltype(map('c'))).name() << std::endl;
std::cout << typeid(decltype(map(std::cout))).name() << std::endl;
std::cout << typeid(decltype(map(1.0))).name() << std::endl;
return 0;
}
答案 1 :(得分:2)
怎么样:
namespace detail{
// To keep exact type
template <typename> struct tag {};
// The mapping
float map(tag<char>);
MyType map(tag<int>);
char map(tag<const int&>);
// ... and so on
}
template <typename T>
using map_t = decltype(detail::map(detail::tag<T>{}));
然后
int main() {
std::cout << typeid(map_t<int>).name() << std::endl;
std::cout << typeid(map_t<const int&>).name() << std::endl;
}