基本上我想做的是如下。假设我们有一个模板成员函数 foo :
template <typename T>
T SomeClass::foo();
以及用户以某种方式通过 map <字符串,int> 作为模板参数:
foo<map<string, int>>();
在定义函数 foo 时,我想做的是获取内部类型 string 和 int 。我尝试了许多猜测工作以使该论据非专业化,但无济于事。
template <map<typename K, typename V>>
map<K, V> SomeClass::foo(); // absolutely illegal
我曾考虑过使用部分专业化,但由于 foo 是类成员函数,因此无法使用。
答案 0 :(得分:1)
如果您想以一种通用的方式从模板中获取内部类型,则可以使用显式专门化:
template <typename T>
struct unpack;
template <template <typename...> class C, typename A, typename B>
struct unpack<C<A, B>>
{
using first = A;
using second = B;
};
用法:
static_assert(std::is_same_v<string,
typename unpack<map<string, int>>::first
>);
static_assert(std::is_same_v<int,
typename unpack<map<string, int>>::second
>);
如果在调用函数时只关心这样做,则可以将该函数作为模板:
template <typename K, typename V>
void foo(std::map<K, V>);
答案 1 :(得分:1)
袖套:
template< class T >
struct Foo
{
static auto impl() -> T;
};
template< class K, class V >
struct Foo< map< K, V > >
{
static auto impl() -> map< K, V >;
};
template< class T >
auto foo()
-> T
{ return Foo<T>::impl(); }
答案 2 :(得分:0)
这是另一种可能的解决方案。方法foo调度到foo_detail方法,该方法将指向T的指针作为参数。该参数未在foo_detail中使用。相反,该参数允许重载分辨率选择调用哪个foo_detail。
由于未使用参数,该解决方案有些笨拙。幸运的是,这可以隐藏在SomeClass的私有部分中,这样SomeClass的用户就不必了解它。
#include <map>
#include <iostream>
#include <string>
#include <typeinfo>
using std::map;
using std::cout;
using std::endl;
using std::string;
class SomeClass
{
public:
template <typename T>
T foo()
{
return foo_detail((T *)0);
}
private:
template<typename T>
T foo_detail(T *)
{
cout << "foo called with type " << typeid(T).name() << endl;
return T();
}
template <typename K, typename V>
map<K, V> foo_detail(map<K, V> *)
{
cout << "foo map specialization called with types "
<< typeid(K).name() << ' ' << typeid(V).name() << endl;
return map<K,V>();
}
};
int main()
{
SomeClass s;
s.foo<double>();
s.foo<map<int, string> >();
return 0;
}