为参数区分大小写t类型 T使用 SFINAE,我想知道是否声明
QVariant::fromValue(t);
和/或
QVariant::value<T>();
编译。如果一个编译通过,另一个也会编译,除非你破解了元类型系统。当且仅当 T 时它们才会编译已使用 Q_DECLARE_METATYPE(T) 声明.
非常简单的用法示例,当且仅当元类型系统支持时(我不需要这个,但这显示了问题)在一个最小的例子中):
template<class T> // enable if T NOT registered in the Qt meta type system
void print(const T &t) {
qDebug() << t;
}
template<class T> // enable if T registered in the Qt meta type system
void print(const T &t) {
qDebug() << QVariant::fromValue<T>();
}
我知道有几种(但相似的)可能性,但它们都引入了一些辅助结构、复杂的 enable_if 等。现在我知道有 QTypeInfo我猜,它已经提供了类似于“在 Qt 元类型系统中声明”的类型特征。但是,此类未记录在案,因此不建议在长期和高效的代码中使用它,因为它可能会在 Qt 版本之间发生变化。
如果类型 T 是否有一种非常简单的方法(比使用“检查器”+ enable_if 更简单)来检查 SFINAE 特化QVariant 支持吗?
请注意,该解决方案在不同的 Qt 版本之间仍应可移植(Qt4 和 Qt5 可能使用不同的 QTypeInfo 定义)。但是,我使用 C++11,所以我可以访问 std::enable_if例如。
“不可移植”的方式是使用内部定义QMetaTypeId2<T>::Defined在enable_if (它是一个定义为 0 或 1 的枚举值)。因此,一个可行的解决方案是:
template<class T>
typename std::enable_if<!QMetaTypeId2<T>::Defined>::type
print(const T &t) {
qDebug() << t;
}
template<class T>
typename std::enable_if<QMetaTypeId2<T>::Defined>::type
print(const T &t) {
qDebug() << QVariant::fromValue<T>();
}
但是,由于 QMetaTypeId2没有记录,只是内部的东西,它不应该出现在客户端代码中。
最佳答案
您应该声明一个可以帮助您的包装器。我能想到的最好的是有几个定义,基于 version Qt 的:
template<typename T>
struct is_registered
{
enum
{
value =
#if QT_VERSION >= 0x050000 // Qt 5.0.0
QMetaTypeId2<T>::Defined
#elif QT_VERSION >= 0x040000 // Qt 4.0.0
QMetaTypeId2<T>::Defined
#endif
};
};
这不是美观的,而是功能性的,在您的代码中您可以使用 is_registered<T>::value无需担心 Qt 的版本。另外,我暂时没有Qt5,所以我不能告诉你是否QMetaTypeId2<T>::Defined是正确的(尽管我认为是)。
不可能使用qMetaTypeId<T>()检查类型是否已注册。事实上,表达式 qMetaTypeId<T>()始终有效,无论类型如何。如果没有注册,函数的body将不会编译(更准确地说:在Qt 4和5中(目前),qMetaTypeId<T>()只调用另一个不编译的函数,如果该类型未注册。因此,您不能使用 SFINAE 对其进行测试。因此,代码 leemes 在他(现已删除)的答案中给出了 will not work as expected。
代码是:
struct _test_is_declared_metatype
{
template<class T>
static auto test(T* t) -> decltype(qMetaTypeId<T>(), std::true_type());
static std::false_type test(...);
};
template<class T>
struct is_declared_metatype : decltype(_test_is_declared_metatype::test<T>(0))
{
};
为什么这行不通?目的是因为调用 qMetaTypeId<T>()在未注册的类型上会导致编译错误,“当类型未注册时,SFINAE 将排除第一个函数”。这里的问题是 qMetaTypeId<T>()始终是一个有效的表达式,所以 qMetaTypeId<T>(), std::true_type()也是,而且decltype(qMetaTypeId<T>(), std::true_type())完美定义(值为 std::true_type )。
这是因为 qMetaTypeId<T>() 的编译错误源于函数的 body,而不是它的原型(prototype)(顺便说一下,只有在 decltype 中的函数被声明并正确调用时,代码才会编译,即没有非模板参数例如模板函数)。
因此,因为 test() 的重载比可变参数更具体,它将始终被选择,因此它将始终“返回”该类型已注册;你可以在下面的测试代码中看到它:
// ----------------------------------------------------------
// qmetatype.h simplification -------------------------------
// ----------------------------------------------------------
template<typename T>
struct metatype
{
enum { defined = 0 };
};
template<typename T>
struct metatype2
{
enum { defined = metatype<T>::defined };
static inline int id() { return metatype<T>::id(); }
};
template <typename T>
inline int metatypeId(
T * /* dummy */ = 0
)
{
return metatype2<T>::id();
}
#define register_meta_type( _type_ ) \
template<> \
struct metatype< _type_ > \
{ \
enum { defined = 1 }; \
static int id() \
{ \
/* Run-time registration in Qt */ \
return __COUNTER__; \
}; \
};
// ----------------------------------------------------------
// ----------------------------------------------------------
// ----------------------------------------------------------
class TestA {};
register_meta_type(TestA)
class TestB {};
class TestC {};
register_meta_type(TestC)
class TestD {};
#include <type_traits>
struct _test_is_declared_metatype
{
/*
metatypeId<T>() is always a valid expression. So this overload is
always taken
*/
template<class T>
static auto test(T* t) -> decltype(metatypeId<T>(), std::true_type());
static std::false_type test(...);
};
template<class T>
struct is_declared_metatype : decltype(_test_is_declared_metatype::test<T>(0))
{
};
#include <iostream>
#define PRINT_DEF( _type_ ) std::cout << #_type_ << " registered ? " << is_declared_metatype< _type_ >::value << "\n";
int main()
{
std::cout << std::boolalpha;
PRINT_DEF(TestA);
PRINT_DEF(TestB);
PRINT_DEF(TestC);
PRINT_DEF(TestD);
}
您可能想要 read more about SFINAE .另外,您可以 read qmetatype.h here .
关于c++ - 检查类型是否被声明为元类型系统(对于 SFINAE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16033719/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/