所以我想编写一个自动的!=
:
template<typename U, typename T>
bool operator!=(U&& u, T&& t) {
return !( std::forward<U>(u) == std::forward<T>(t) );
}
但这是不礼貌的1。所以我写
// T() == U() is valid?
template<typename T, typename U, typename=void>
struct can_equal:std::false_type {};
template<typename T, typename U>
struct can_equal<
T,
U,
typename std::enable_if<
std::is_convertible<
decltype( std::declval<T>() == std::declval<U>() ),
bool
>::value
>::type
>: std::true_type {};
template<typename U, typename T,
typename=typename std::enable_if<can_equal<T,U>::value>::type
>
bool operator!=(U&& u, T&& t) {
return !( std::forward<U>(u) == std::forward<T>(t) );
}
struct test {
};
bool operator==(const test&, const test&);
bool operator!=(const test&, const test&);
因此,我编写了这个特征类:
template<typename T, typename U,typename=void>
struct can_not_equal // ... basically the same as can_equal, omitted
它测试t!=u
是否有效。
然后对!=
进行如下扩充:
template<typename U, typename T,
typename=typename std::enable_if<
can_equal<T,U>::value
&& !can_not_equal<T,U>::value
>::type
>
bool operator!=(U&& u, T&& t) {
return !( std::forward<U>(u) == std::forward<T>(t) );
}
脚注1:如果创建模板
,SFINAE将认为每对类型之间都有一个有效的!=
。然后,当您试图实际调用!=
时,它被实例化,并且编译失败。在此基础上,您可以使用bool操作符!=(const foo&,const foo&)
函数,因为您可以更好地匹配foo()!=foo()
和fooa,b;a!=b;
。我认为做这两件事都是不礼貌的。
您的方法的问题似乎是操作符!=
的回退全局定义太吸引人了,您需要进行SFINAE检查才能排除它。但是,SFINAE检查依赖于函数本身用于重载解析的资格,从而导致在类型演绎期间(尝试)无限递归。
在我看来,任何基于SFINAE的类似尝试都将遇到同样的问题,因此在我看来,最明智的方法是首先降低运算符!=
对重载解决的吸引力,然后让运算符!=
的其他合理编写的重载(这将在稍后清楚地说明)优先。
给定您提供的类型特征CAN_EQUAL
:
#include <type_traits>
#include <functional>
template<typename T, typename U, typename=void>
struct can_equal : std::false_type {};
template<typename T, typename U>
struct can_equal<
T,
U,
typename std::enable_if<
std::is_convertible<
decltype( std::declval<T>() == std::declval<U>() ),
bool
>::value
>::type
>: std::true_type {};
我将这样定义回退运算符!=
:
template<typename T, typename U>
bool is_not_equal(T&& t, U&& u)
{
return !(std::forward<T>(t) == std::forward<U>(u));
}
template<
typename T,
typename... Ts,
typename std::enable_if<can_equal<T, Ts...>::value>::type* = nullptr
>
bool operator != (T const& t, Ts const&... args)
{
return is_not_equal(t, args...);
}
据我所知,运算符!=
的任何重载只要定义了两个函数参数(所以没有参数包)就更适合重载解析。因此,只有在没有更好的重载时,才会选择操作符!=
的上述回退版本。而且,只有当can_equal<>
类型特征返回true
时,才会选择它。
我已经根据您准备的SSCE测试了这一点,其中定义了四个结构
以及操作符==
和操作符!=
的重载:
struct test { };
bool operator==(const test&, const test&) { std::cout << "(==)"; return true; }
bool operator!=(const test&, const test&) { std::cout << "(!==)"; return true; }
struct test2 { };
struct test3 { };
bool operator == (const test3&, const test3&)
{ std::cout << "(==)"; return true; }
struct test4 { };
template<typename T,
EnableIf< std::is_convertible< T, test4 const& >::value >... >
bool operator == ( T&&, T&& ) { std::cout << "(==)"; return true; }
template<typename T,
EnableIf< std::is_convertible< T, test4 const& >::value >... >
bool operator != ( T&&, T&& ) { std::cout << "(!=)"; return true; }
template<typename T, typename U>
bool is_not_equal(T&& t, U&& u)
{
std::cout << "!"; // <== FOR TESTING PURPOSES
return !(std::forward<T>(t) == std::forward<U>(u));
}
std::cout << (a != b) << "\n"; // #1
std::cout << (test3() != test3()) << "\n"; // #2
std::cout << (test4() != test4()) << "\n"; // #3
关于第一个测试,运算符!=
是为类型test
定义的,因此#1
行应该打印:
(!==)1
关于第二个测试,运算符!=
没有为test3
定义,test3
不能转换为test4
,因此我们的全局运算符!=
应该起作用,并否定运算符==
的重载结果,该重载取两个常量test3&
。因此,第#2
行应打印:
!(==)0 // operator == returns true, and is_not_equal() negates it
最后,第三个测试涉及两个类型为test4
的rvalue对象,为其定义了operator!=
(因为参数可转换为test4 const&
)。因此,第#3
行应该打印:
(!=)1
这里有一个现场示例,表明所产生的输出是预期的。
模板中有一些HTML元素,例如模板/电子邮件/电子邮件标题。php第41行,没有内联样式: 但当它在前端渲染时,它会以许多内联样式出现: 如何以及在哪里进行这种风格的注射? 如何避免这种风格的注射? 我想在模板中编写自己的内联样式。做这件事的正确方法是什么? 我注意到,一些注入,比如上面的例子,取决于元素的ID,所以我可以删除它们的ID,但其他情况下是可变的,比如模板/电子邮件/电子邮件头。php
问题内容: 我的问题是我必须在try语句中设置变量,否则会出现编译错误。 稍后我需要使用该变量,但现在超出了范围,所以我相信。我在try语句外部初始化了该变量并将其设置为null,我以为可以在外部访问它,但仍然得到了。 下面的代码,其中有很多代码使阅读变得更容易-我知道这是不好的代码,但是我是Servlets的新手,只想看看它与所有活动部件一起运行时应如何工作。 我创建了另一个类,该类调用crea
如果我有一个默认模板类型的模板类,我必须编写模板尖括号。有没有可能避免这种情况? 示例: 到目前为止,我都是通过一个单独的名称空间和重新定义类来实现这一点的: 问题是,如果我想将类与其他类型一起使用,我必须检查名称空间detail_。有没有另一种解决方案,我还没有看到。
需要在一个PDF文件中导出所有的表单,所以我找到了这段代码,它工作(导出一个单PDF,每个表单有一页)。但是我不想使用select/active语句,我更喜欢使用存储对象的变量。 问题:在这段代码中如何避免select/ActiveSheet?
问题内容: 建议在HTML页面中使用表格(现在已经有了CSS)? 表格有什么用途?表具有哪些CSS所没有的功能? 问题答案: 一点都不。但是将表格用于表格数据。只是不要将它们用于一般布局。 但是,如果您显示表格数据(例如结果或什至是表格),请继续使用表格!
本文向大家介绍如何避免MySQL查询中的OR语句过多?,包括了如何避免MySQL查询中的OR语句过多?的使用技巧和注意事项,需要的朋友参考一下 使用MySQL避免太多的OR语句。让我们首先创建一个表- 使用插入命令在表中插入一些记录- 使用select语句显示表中的所有记录- 这将产生以下输出- 以下是避免在MySQL查询中使用太多OR语句的查询,即使用- 这将产生以下输出-