std::模板成员函数指针的映射
std::map of template member function pointers
我正在阅读这个问题的答案,并试图弄清楚如何在std::map
中存储模板成员函数指针 c++11。
class A {
template<typename T>
using MFP = T (A::*)();
std::map <string, MFP> fmap;
template<typename T>
T f() { return 1; }
template<typename T>
T g() { return 1.0f; }
A() {
fmap.insert(std::make_pair( "f", &A::f));
fmap.insert(std::make_pair( "g", &A::g));
}
template<typename T>
T Call(const string & s) {
MFP fp = fmap[s];
return (this->*fp)();
}
};
类型别名编译,但是当我在std::map
声明中使用它时,出现以下错误:
error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’
std::map<std::string, MFP> fmap;
有什么想法吗?
正如 Sam 注意到的那样,MFP
是一个模板,而 std::map
的第二个模板参数需要一个类型。因此,在使用函数指针填充映射之前,需要获取实际类型。让我为这种情况提出最直接的方法 - 模板类。有了它,您需要在对象实例化时列出所有所需的返回类型,但您将能够使用任何这些类型Call
。我将使用 std::function
s 而不是指针,但您可以轻松地回滚到函数指针。
首先,我们不知道类用户需要多少种类型,所以让我们让它变频。由于map
需要一个完整的类型,我们需要一堆地图 - 每种类型一个。最常见的获取方法是元组,在我们的例子中需要扩展包。使用元组,我们可以在编译时搜索所需的映射,然后在运行时按名称搜索其中的函数。看看带有解释的代码:
template<typename ...Types>
class B {
private:
// Template alias for std::function.
template<typename T>
using MFP = std::function<T()>;
/* Tuple of maps from std::string to MFP for all types
in Types parameter pack. */
std::tuple<std::map<std::string, MFP<Types>>...> fmap;
template<typename T>
T f() { return 2.5; }
template<typename T>
T g() { return 1.0f; }
// Call implementation with compile-time pattern matching.
// T is return type, U is current matching type
template<typename T, size_t idx, typename U, typename ...Ts>
struct CallImpl {
static T callImpl(B* this_ptr, const std::string & s) {
/* If we exhausted Ts pack, we have no proper instance for
requested return type. Let's print a human-readable
compilation error message. */
static_assert((sizeof ... (Ts)) > 0,
"Requested return type not found.");
/* Otherwise discard U, increment tuple index
and try the next type. */
return CallImpl<T, idx + 1, Ts...>::callImpl(this_ptr, s);
}
};
/* This partial specialization is called when return
* type (T in above declaration) matches
* stored type (U in above declaration). */
template<typename T, size_t idx, typename ...Ts>
struct CallImpl<T, idx, T, Ts...> {
static T callImpl(B* this_ptr, const std::string & s) {
/* First, get the map from tuple by index.
This operation is either always valid in runtime or does not compile.
Next, get function object from map. It may fail in runtime
if user passed invalid string, so consider using map::at
or add any other sensible logic for this case. */
return std::get<idx>(this_ptr->fmap)[s]();
}
};
public:
B() {
/* Populate map with objects. Ellipsis in the last line
expands Types as needed. */
fmap = std::make_tuple(std::map<std::string, MFP<Types>>{
{"f", std::bind(std::mem_fn(&B::f<Types>), this)},
{"g", std::bind(std::mem_fn(&B::g<Types>), this)}
}...);
}
template<typename T>
T Call(const std::string & s) {
/* Start pattern matching with zero index. */
return CallImpl<T, 0, Types...>::callImpl(this, s);
}
};
用法:
int main() {
B<int, float, short> a; // Provides int, float and short return types.
std::cout << a.Call<int>("f") << std::endl; // Prints 2, which is 2.5 casted to int.
std::cout << a.Call<float>("f") << std::endl; // Prints 2.5
// Compilation error with "Requested type not found." message among others.
std::cout << a.Call<double>("f") << std::endl;
}
一些注意事项:
f
是双文字,但双精度没有列在B<int, float> a;
中,这我们在a.Call<double>("whatever")
上得到编译错误。Call
方法的代码和callImpl
函数short
根本没有生成,因为我们没有实例化它。
2.5
在声明中std::map
的第二个模板参数是映射值的类或类型。例如:
std::map<std::string, int> mapsi;
第二个模板参数是类型 int
,一个整数。
您的声明:
std::map <string, MFP> fmap;
MFP
不是一个类,也不是一个类型。 MFP
是另一个模板。这相当于写入:
std::map <string, template<typename T> T (A::*)()> fmap;
这是没有道理的。因此编译错误。
你可以这样写:
std::map <string, MFP<int>> fmap;
或
std::map <string, MFP<std::string>> fmap;
MVP<int>
和MFP<std::string>
是实际类型,实际类,因此您可以将它们放入地图中。不能将模板放入地图中,因为模板不是实际的类或类型。
template<typename T>
T f() { return 1; }
template<typename T>
T g() { return 1.0f; }
您显然认为这些是成员函数。他们不是。它们是成员模板。没有指向成员模板的指针,只有指向成员函数的指针。
相关文章:
- 如何创建对象函数指针C++映射?
- c++:复制、删除和运算符=在原始指针映射中
- 尝试通过指针映射访问类成员
- 使用函数指针映射时的 C++ 调用函数
- 将新元素推送到函数指针映射中 "inline" ?
- 如何在C 11中创建指针映射以静态成员功能
- 方法指针映射,编译器说他们不接受任何参数
- 从指针映射调用函数,指向具有可变数量参数的函数
- 如何使用boost::与函数指针映射正确绑定
- std::按值或指针映射操作
- 将函数指针映射到 std::string
- 指向指针向量的指针映射的错误
- 使用C++中的函数指针映射枚举键和值
- 创建指向成员函数的指针映射
- 无法从指向多态类的指针映射获取有效的指针
- C++ - 通过 getter 函数在单独的类中从对象指针映射访问成员函数
- 指向成员函数的指针映射:无法将 void (*) 转换为 void (对象::*)
- std::基类指针映射
- 为对象指针映射编写函数模板时出现问题
- 指针映射的数组下标运算符