- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试找到一个工作类型特征来检测给定类型是否具有 std::ostream
的左移运算符重载(例如,可与 std::cout
或 boost::lexical_cast
互操作)。我在 boost::has_left_shift
上取得了成功除了类型是 POD 或 std::string
的 STL 容器的情况类型。我怀疑这与 STL 类型或 operator<< 函数的特化有关。使用 std::ostream
的有效左移运算符一般识别类型的正确方法是什么? ?如果那不可行,是否有单独的方法来检测 POD 或 std::string 类型的 STL 容器上左移运算符的过载?
下面的代码显示了我目前正在使用的内容,并演示了如何 boost::has_left_shift
未能检测到过载 operator<<
函数,即使它在下一行被调用。该程序在 GCC 4.5.1 或更高版本和 clang 3.1 中编译和运行。
为了避免明显的 react ,我尝试替换模板化的 operator<<
各种类型的特定版本的功能用于无济于事。我还为这两种类型尝试了 const-ness 和 l-value/r-value 说明符的各种组合(各种调整使我看到一条编译器消息,指向带有 r-value ostream 的 operator<<
重载)。我也尝试过实现我自己的特征,它最多给我与 boost::has_left_shift
相同的结果。 .
在此先感谢您提供的任何帮助。如果可以包含对为什么会发生这种行为以及解决方案如何工作的详尽解释,我也将不胜感激。我正在扩展我的模板知识的极限,很想知道为什么这不像我想象的那样有效。
#include <string>
#include <vector>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/type_traits/has_left_shift.hpp>
using namespace std;
struct Point {
int x;
int y;
Point(int x, int y) : x(x), y(y) {}
string getStr() const { return "("+boost::lexical_cast<string>(x)+","+boost::lexical_cast<string>(y)+")"; }
};
ostream& operator<<(ostream& stream, const Point& p)
{
stream << p.getStr();
return stream;
}
template <typename T>
ostream& operator<<(ostream& stream, const std::vector<T>& v)
{
stream << "[";
for(auto it = v.begin(); it != v.end(); ++it)
{
if(it != v.begin())
stream << ", ";
stream << *it;
}
stream << "]";
return stream;
}
template <typename T>
void print(const string& name, T& t)
{
cout << name << " has left shift = " << boost::has_left_shift<ostream , T>::value << endl;
cout << "t = " << t << endl << endl;
}
int main()
{
cout << boolalpha;
int i = 1;
print("int", i);
string s = "asdf";
print("std::string", s);
Point p(2,3);
print("Point", p);
vector<int> vi({1, 2, 3});
print("std::vector<int>", vi);
vector<string> vs({"x", "y", "z"});
print("std::vector<std::string>", vs);
vector<Point> vp({Point(1,2), Point(3,4), Point(5,6)});
print("std::vector<Point>", vp);
}
最佳答案
它不起作用的原因是 C++ 有时有令人惊讶的(但动机良好的)解析函数调用的规则。特别是,名称查找首先在调用发生的命名空间和参数的命名空间(对于 UDT)中执行:如果找到具有匹配名称(或匹配的内置运算符)的函数,则选择它(或者如果找到多个,则执行重载决议)。
仅当在参数的命名空间中找不到具有匹配名称的函数时,才会检查父命名空间。如果找到具有匹配名称的函数但无法解析调用,或者调用不明确,编译器将不会继续在父命名空间中查找以期找到更好或明确的匹配:相反,它会结论是没有办法解决调用。
很好地解释了这种机制in this presentation by Stephan T. Lavavej在this old article by Herb Sutter .
在您的例子中,检查此运算符是否存在的函数在 boost
中命名空间。您的论点来自 std
命名空间 ( ostream
, string
, vector
) 或 POD ( int
)。在std
命名空间,operator <<
的不可行 重载存在,因此编译器不会费心在定义重载的父(全局)命名空间中查找。它会简单地得出结论,在 boost
中完成的(模拟)调用命名空间检查是否operator <<
已定义无法解析。
现在boost::has_left_shift
很可能有一些 SFINAE 机制将编译错误转化为失败的替换,并将分配 false
到 value
静态变量。
更新:
答案的原始部分解释了为什么这不起作用。现在让我们看看是否有办法解决它。由于使用了 ADL,并且 std
命名空间包含不可行的重载 operator <<
, 事实上 阻止了解决调用的尝试,人们可能会想移动 operator <<
的可行 重载。从全局命名空间到 std
命名空间。
唉,扩展std
命名空间(如果我们要添加 operator <<
的新重载,我们就会这样做)被 C++ 标准禁止。允许的是专门化 std
中定义的模板函数。命名空间(除非另有说明);然而,这对我们没有帮助,因为没有模板的参数可以被 vector<int>
专门化。 .此外,函数模板不能部分特化,这会使事情变得更加笨拙。
不过还有最后一种可能性:将重载添加到调用解析发生的命名空间。这是 Boost.TypeTraits 机制内部的某个地方。特别是,我们感兴趣的是进行调用的命名空间的名称。
在当前版本的库中,它恰好是 boost::detail::has_left_shift_impl
,但我不确定这在不同的 Boost 版本中的可移植性如何。
但是,如果您真的需要解决方法,您可以在该命名空间中声明您的运算符:
namespace boost
{
namespace detail
{
namespace has_left_shift_impl
{
ostream& operator<<(ostream& stream, const Point& p)
{
stream << p.getStr();
return stream;
}
template <typename T>
std::ostream& operator<<(std::ostream& stream, const std::vector<T>& v)
{
stream << "[";
for(auto it = v.begin(); it != v.end(); ++it)
{
if(it != v.begin())
stream << ", ";
stream << *it;
}
stream << "]";
return stream;
}
}
}
}
一切都会开始运作。
不过有一个警告:虽然它可以在 GCC 4.7.2 上正常编译和运行,并具有预期的输出。但是,Clang 3.2 似乎要求在 boost::details::has_left_shift_impl
中定义重载。 之前 has_left_shift.hpp
包含 header 。我认为这是一个错误。
关于c++ - 测试是否存在左移运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14569768/
我获得了一些源代码示例,我想测试一些功能。不幸的是,我在执行程序时遇到问题: 11:41:31 [linqus@ottsrvafq1 example]$ javac -g test/test.jav
我想测试ggplot生成的两个图是否相同。一种选择是在绘图对象上使用all.equal,但我宁愿进行更艰巨的测试以确保它们相同,这似乎是identical()为我提供的东西。 但是,当我测试使用相同d
我确实使用 JUnit5 执行我的 Maven 测试,其中所有测试类都有 @ExtendWith({ProcessExtension.class}) 注释。如果是这种情况,此扩展必须根据特殊逻辑使测试
在开始使用 Node.js 开发有用的东西之前,您的流程是什么?您是否在 VowJS、Expresso 上创建测试?你使用 Selenium 测试吗?什么时候? 我有兴趣获得一个很好的工作流程来开发我
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 3 年前。 基于示例here ,我尝试为我的
我正在考虑测试一些 Vue.js 组件,作为 Laravel 应用程序的一部分。所以,我有一个在 Blade 模板中使用并生成 GET 的组件。在 mounted 期间请求生命周期钩子(Hook)。假
考虑以下程序: #include struct Test { int a; }; int main() { Test t=Test(); std::cout<
我目前的立场是:如果我使用 web 测试(在我的例子中可能是通过 VS.NET'08 测试工具和 WatiN)以及代码覆盖率和广泛的数据来彻底测试我的 ASP.NET 应用程序,我应该不需要编写单独的
我正在使用 C#、.NET 4.7 我有 3 个字符串,即。 [test.1, test.10, test.2] 我需要对它们进行排序以获得: test.1 test.2 test.10 我可能会得到
我有一个 ID 为“rv_list”的 RecyclerView。单击任何 RecyclerView 项目时,每个项目内都有一个可见的 id 为“star”的 View 。 我想用 expresso
我正在使用 Jest 和模拟器测试 Firebase 函数,尽管这些测试可能来自竞争条件。所谓 flakey,我的意思是有时它们会通过,有时不会,即使在同一台机器上也是如此。 测试和函数是用 Type
我在测试我与 typeahead.js ( https://github.com/angular-ui/bootstrap/blob/master/src/typeahead/typeahead.js
我正在尝试使用 Teamcity 自动运行测试,但似乎当代理编译项目时,它没有正确完成,因为当我运行运行测试之类的命令时,我收到以下错误: fatal error: 'Pushwoosh/PushNo
这是我第一次玩 cucumber ,还创建了一个测试和 API 的套件。我的问题是在测试 API 时是否需要运行它? 例如我脑子里有这个, 启动 express 服务器作为后台任务 然后当它启动时(我
我有我的主要应用程序项目,然后是我的测试的第二个项目。将所有类型的测试存储在该测试项目中是一种好的做法,还是应该将一些测试驻留在主应用程序项目中? 我应该在我的主项目中保留 POJO JUnit(测试
我正在努力弄清楚如何实现这个计数。模型是用户、测试、等级 用户 has_many 测试,测试 has_many 成绩。 每个等级都有一个计算分数(strong_pass、pass、fail、stron
我正在尝试测试一些涉及 OkHttp3 的下载代码,但不幸失败了。目标:测试 下载图像文件并验证其是否有效。平台:安卓。此代码可在生产环境中运行,但测试代码没有任何意义。 产品代码 class Fil
当我想为 iOS 运行 UI 测试时,我收到以下消息: SetUp : System.Exception : Unable to determine simulator version for X 堆
我正在使用 Firebase Remote Config 在 iOS 上设置 A/B 测试。 一切都已设置完毕,我正在 iOS 应用程序中读取服务器端默认值。 但是在多个模拟器上尝试,它们都读取了默认
[已编辑]:我已经用 promise 方式更改了我的代码。 我正在写 React with this starter 由 facebook 创建,我是测试方面的新手。 现在我有一个关于图像的组件,它有
我是一名优秀的程序员,十分优秀!