- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要创建一个尽可能通用的函数,假设我有几个 map
s 一起工作 --
int main()
{
map<int, string> m1 = {{0, "abc"}, {1, "def"}, {2, "ghi"}} ;
map<int, double> m2 = {{0, 0.5}, {1, 0.6}, {2, 0.7}} ;
map<int, vector<string>> m3 = {{0, {"abc", "def"}},
{1, {"ghi", "ijk"}}};
dosomething(m1);
dosomething(m2);
}
和我的 template
d dosomething()
函数看起来像这样——
template <typename A, typename B>
void dosomething(map<A,B> m)
{
for(auto e : m)
{
// do something with e
}
}
现在,如果我想编写一个适用于任何类型的 map
的函数(即 map<int, vector<string>
或 map<int, string>
或 map<int, double>
)我该怎么做?如果我能做这样的事情那就太好了 --
template <typename A, typename B>
void dosomething(map<A,B> m)
{
for(auto me: m)
{
if (the type of B is not a standard container type)
{
// do something with me.second
}
else if(the type of B is a something from the standard container)
{
for(int i = 0 ; i < (me.second).size() ; i++)
// do something with me.second[i]
}
}
}
我如何在 C++ 中做到这一点?我假设编译器遵循 c++11 规范。
最佳答案
模板实例化中的代码是为了编译。因此,当根据模板参数的类型做不同的事情时,您通常不能将它们放在一个函数中。相反,您会将处理委托(delegate)给适当重载的函数,该函数本身可能是有条件适用的模板。例如,您的 dosomething()
函数可能如下所示:
// suitable declaration/definition of dosomething_apply() go here; see below
template <typename A, typename B>
void dosomething(std::map<A, B> const& m) {
for (auto&& me: m) {
dosomething_apply(me.second);
}
}
顺便说一句:不要使用for (auto e: m)
除非您有充分的理由需要此表格!在大多数情况下,这是一个性能问题。同样,您不应按值传递更大的对象,而应使用合适的引用类型传递它们。
有点棘手的事情是确定参数是否为 dosomething_apply()
是否是标准容器:当然没有类型特征将所有标准分类为这样。不过,可以创建相应的类型特征。下一个问题是这是否真的是您想要检测的,因为您在元素上使用索引的假设布局意味着 me.second
有一个基于索引的下标运算符,仅对 std::vector<...>
为真, std::dequeue<...>
, std::basic_string<...>
, std::array<...>
, 和 std::bitset<...>
(不确定这是否是提供下标的完整容器集)。还有其他容器不进行下标操作,例如std::list<...>
, std::map<...>
, std::unordered_map<...>
等
不过,所有这些容器(std::bitset<...>
除外)都提供迭代器接口(interface)。在 dosomething_apply()
的实现中检测一个类型是否提供迭代器接口(interface)并使用该接口(interface)可能更合理.由于您似乎设置为使用基于索引的下标,因此下面的示例处理了上面提到的类模板集。
第一步是创建一个合适的特征类,它检测需要特殊处理的所需类型。在许多情况下,可以检测到是否存在合适的成员函数或成员类型。由于您特别要求标准类型,因此有必要列出支持的类型,因为也可以检测非标准类的成员函数或成员类型。这是一个名为 is_subscripted
的示例特征类:
template <typename T>
struct is_subscripted: std::false_type {};
template <typename T, std::size_t N>
struct is_subscripted<std::array<T, N>>: std::true_type {};
template <std::size_t N>
struct is_subscripted<std::bitset<N>>: std::true_type {};
template <typename cT, typename Al>
struct is_subscripted<std::deque<cT, Al>>: std::true_type {};
template <typename cT, typename Tr, typename Al>
struct is_subscripted<std::basic_string<cT, Tr, Al>>: std::true_type {};
template <typename cT, typename Al>
struct is_subscripted<std::vector<cT, Al>>: std::true_type {};
它只是创建了一个默认版本的 trait,声明该 trait 与 std::false_type
的派生不匹配。 .然后相应的模板专门用于上面列出的类模板,每个模板都来自 std::true_type
。 .这样一个形式的表达式 is_specialized<T>::value
可用于检测特征是否适用于类型 T
.
下一步是提供合适的处理函数。由于特征存在或不存在,使用 enable_if_t<...>
是一个简单的方法:
template <typename T>
std::enable_if_t<!is_subscripted<T>::value>
dosomething_apply(T const& value) {
std::cout << "value=" << value << '\n';
}
template <typename T>
std::enable_if_t<is_subscripted<T>::value>
dosomething_apply(T const& range) {
for (auto size(range.size()), i(size - size); i != size; ++i) {
std::cout << "range=" << range[i] << '\n';
}
}
使用 std::enable_if_t<Value>
用Value
评估为 true
产量 void
(使用第二个参数,例如 std::enable_if_t<Value, double>
以获得不同的类型)并且函数模板变得适用。与 Value
一起使用评估为 false
不产生类型并且函数模板被忽略(有关正在发生的事情的解释,请参阅 SFINAE)。
... 就是这样。把一个合适的程序放在一起所需要的一切,一切都应该有效。下面是一个完整的程序,可以提供给 C++14 编译器。上面的代码中有一些 C++14 的次要用途,例如使用 std::enable_if_v<T>
而不是 typename std::enable_if<T>::type
.如果您需要通过适用于先前 C++ 标准的编译器传递代码,那么将 C++14 用法替换为 C++11 用法应该相对简单。
#include <map>
#include <iostream>
#include <utility>
#include <array>
#include <bitset>
#include <deque>
#include <string>
#include <vector>
// ----------------------------------------------------------------------------
template <typename T>
struct is_subscripted: std::false_type {};
template <typename T, std::size_t N>
struct is_subscripted<std::array<T, N>>: std::true_type {};
template <std::size_t N>
struct is_subscripted<std::bitset<N>>: std::true_type {};
template <typename cT, typename Al>
struct is_subscripted<std::deque<cT, Al>>: std::true_type {};
template <typename cT, typename Tr, typename Al>
struct is_subscripted<std::basic_string<cT, Tr, Al>>: std::true_type {};
template <typename cT, typename Al>
struct is_subscripted<std::vector<cT, Al>>: std::true_type {};
// ----------------------------------------------------------------------------
template <typename T>
std::enable_if_t<!is_subscripted<T>::value>
dosomething_apply(T const& value) {
std::cout << "value=" << value << '\n';
}
template <typename T>
std::enable_if_t<is_subscripted<T>::value>
dosomething_apply(T const& range) {
for (auto size(range.size()), i(size - size); i != size; ++i) {
std::cout << "range=" << range[i] << '\n';
}
}
// ----------------------------------------------------------------------------
template <typename A, typename B>
void dosomething(std::map<A, B> const& m)
{
for (auto&& me: m) {
dosomething_apply(me.second);
}
}
int main()
{
dosomething(std::map<int, int>{ { 1, 2 }, {3, 4 } });
dosomething(std::map<int, std::array<int, 2> >{ { 1, { { 2, 3 }} }, {4, { { 5, 6 } } } });
dosomething(std::map<int, std::bitset<4> >{ { 1, std::bitset<4>("1010") }, {2, std::bitset<4>("0011") } });
dosomething(std::map<int, std::deque<int>>{ { 10, { { 12, 13, 14 } } }, { 20, { 22, 23, 24 } } });
dosomething(std::map<int, std::string>{ { 1, "one" }, {2, "two" } });
dosomething(std::map<int, std::vector<int>>{ { 30, { { 32, 33, 34 } } }, { 40, { 42, 43, 44 } } });
}
关于c++使用模板制作最通用的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26643900/
我想在一个页面上做一个按钮,可以在同一页面调用一个JS函数。该函数将需要创建(打开)新窗口,其 HTML 代码由 JS 函数本身提供。我该怎么做? 这样做的目的是从特定页面生成一个打印友好的页面。 请
我一直在用 php 开发这个项目。该项目的一半是使用 mysql_query 完成的,最新的模块是使用 mysqli 制作的。有很多模块,我不想更改代码。如果是这样的话会不会产生问题。或者我应该将其全
我安装了好几次 qt creator,但它从来没有像我现在的 PC 那样花钱;首先,我使用我的 Pendrive(Qt 5.8 的)上一直有的安装程序,告诉我我无法下载一些存储库,我下载了相同安装程序
我安装了 Qt Creator 5.10.1,当我构建项目时出现错误:“无法确定要运行哪个”make“命令。检查构建配置中的”make“步骤。”。 我已经在另一台 PC 上安装了 Qt,我看到了这个问
看看这个 makefile,它有某种原始的进度指示(可能是一个进度条)。 请给我建议/意见! # BUILD 最初是未定义的 ifndef 构建 # max 等于 256 个 x 十六:= x x x
这个问题会有点长,对此我很抱歉:) 我花了几天时间寻找最好的解决方案,以在 asp mvc 和 JQuery 中制作图像库。 主要问题是当用户点击拇指时显示图像。 我想让整个浏览器 View 变成黑色
我是Python方面的 super 高手。我一直在努力寻找适当的解决方案。这是列表,L = [0, 0, 0, 3, 4, 5, 6, 0, 0, 0, 0, 11, 12, 13, 14, 0, 0
让我们考虑两个简化的 CMakeLists.txt set(GTEST "/usr/local/lib/libgtest.a") set(GMOCK "/usr/local/lib/libgmock.
我如何制作 Makefile,因为这是按源代码分发程序的最佳方式。请记住,这是针对 C++ 程序的,而我是从 C 开发领域开始的。但是可以为我的 Python 程序制作 Makefile 吗? 最佳答
由于 Ord 是 Eq 的子类,我发现很难理解创建该类的新类型实例的样子。 我已经设法做到了: newtype NT1 = NT1 Integer instance Eq NT1 wh
在 PowerShell 中,我想编写一个函数,它接受不同的选项作为参数。没关系,如果它接收多个参数,但它必须接收至少一个参数。我想通过参数定义而不是之后的代码来强制执行它。我可以使用以下代码让它工作
我正在通过构建包使用 enable-ssl 在 heroku (ubuntu) 上安装 ffmpeg。我能够一直构建到这些错误: install: cannot create regular file
我是 FFmpeg 的新手,但作为一个学习一些 mysql 数据库的项目,我正在尝试创建一个视频上传网站。 当我尝试使用此代码制作缩略图时: shell_exec("/usr/local/bin/ff
我想要一个绘制可绘制对象的 Actor ,但将其剪辑为 Actor 的大小。我从 Widget 派生这个类,并使用一些硬编码的值作为一个简单的测试: public class MyWidget ext
我一直在查看 Faxien+Sinan 和 Rebar,Erlang OTP 的基本理念似乎是,在单个 Erlang 镜像实例上安装应用程序和版本。保持发布自包含的最佳实践是什么?有没有办法打包发布,
我正在尝试克隆存储库,但它应该是彼此独立的副本。这背后有什么魔法吗,或者只是使用 svn 客户端并克隆它? 谢谢 最佳答案 试试 svnadmin hotcopy .您可以在 repo mainten
我想做一个这样的菜单: Item 1 Item 2 Item 3 Subitem 1 Subitem 2 但我得到了这个:
为 Yii 创建扩展的最佳方式是什么? 这是我到目前为止所做的 我希望它可以通过 composer 安装,所以我为它创建了一个 github repo。 我在文件夹 vendor/githubname
我尝试制作一个ActionListener,但它给了我一个错误。我导入了事件,但它仍然不起作用。这是我的代码: send.addActionListener(new jj); private clas
我需要能够将 div 内的 HTML 代码恢复为页面就绪状态。我需要这个,因为我想在页面准备好后对 HTML 代码进行一些更改,然后在需要时将其恢复到页面准备好时的状态.. 我想使用克隆,但是如何只复
我是一名优秀的程序员,十分优秀!