gpt4 book ai didi

c++ - 在编译时为 C++ 中的成员函数添加别名

转载 作者:可可西里 更新时间:2023-11-01 17:55:34 30 4
gpt4 key购买 nike

假设我有一些通用代码,我想将其重用于实现相同底层功能但具有不同成员函数名称的接口(interface)的多个类。例如,如果底层类具有 erase,则以下代码将起作用成员函数,例如std::setstd::unordered_set .

template <typename T>
static std::chrono::duration<double> set_insert_time(const typename T::value_type &v) {
T set;
std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
start = std::chrono::high_resolution_clock::now();
set.erase(v);
end = std::chrono::high_resolution_clock::now();
return end - start;
}

但是,现在我希望这个函数可以与例如tbb::concurrent_unordered_set , 它提供了一个名为 unsafe_erase 的函数相反。

我最初的方法是通过定义以下内容并调用 set_ops<T>::erase(set, v) 来利用具有部分模板特化的类型特征。反而。不幸的是,这不能编译,因为 tbb::concurrent_unordered_set是模板类而不是类型。我还尝试使用键类型的第二个模板参数来扩展类型特征,但这无法编译,因为 T不是 std::mem_fn(&T<U>::erase) 中的模板.

template <typename T>
struct set_ops {
constexpr static auto erase = std::mem_fn(&T::erase);
};

template <>
struct set_ops<tbb::concurrent_unordered_set> {
constexpr static auto erase = std::mem_fn(&T::unsafe_erase);
};

我也试过用函数模板包装成员函数,如下。这似乎可以编译,但由于 undefined reference 而无法链接,例如decltype ((({parm#1}.erase)({parm#2})),((bool)())) erase<std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> > >(std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >&, std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >::key_type const&)

template <typename T>
constexpr auto set_erase(T& s, const typename T::key_type &v) -> decltype(s.erase(v), bool());
template <typename T>
constexpr auto set_erase(T& s, const typename T::key_type &v) -> decltype(s.unsafe_erase(v), bool());

我应该如何在编译时执行这个别名?我知道我可以为每个底层类提供一个从抽象接口(interface)继承的实现,或者使用指向成员函数的指针,但我想避免任何运行时开销。

最佳答案

您可以在辅助结构中提供简单的包装函数以及部分特化:

template <typename T>
struct set_ops {
static auto erase(T& t, const T::value_type& obj) {
return t.erase(obj);
}
};

template <typename... T>
struct set_ops<tbb::concurrent_unordered_set<T...>> {
using set_type = tbb::concurrent_unordered_set<T...>;
static auto erase(set_type& t, const typename set_type::value_type& obj) {
return t.unsafe_erase(obj);
}
};

那么您的set_inert_time 函数将如下所示:

template <typename T>
static std::chrono::duration<double> set_insert_time(const typename T::value_type &v) {
T set;
std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
start = std::chrono::high_resolution_clock::now();
set_ops<T>::erase(set, v);
end = std::chrono::high_resolution_clock::now();
return end - start;
}

这避免了成员函数指针的所有乱七八糟,并使所有内容都可以在编译时很好地解析。

关于c++ - 在编译时为 C++ 中的成员函数添加别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46066194/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com