我有一些类型,每个类型都有同名的子类型:
struct TypeA {
typedef int subtype;
};
struct TypeB {
typedef float subtype;
};
还有没有此子类型但在相同上下文中使用的类型:
struct TypeC {
// (no subtype defined)
};
如何添加提供自定义编译错误消息的虚拟子类型?
我(迄今为止未成功)的尝试是:
struct TypeC {
struct subtype {
static_assert(false, "Attempt to access the non-existent subtype of TypeC.");
};
};
但是static_assert(false, ...)无法工作,因为即使从未访问该类型,编译器也会抛出错误。
如何延迟对 static_assert 的评估?到类型被访问的时间?
一个失败的尝试是引入一个虚拟枚举并从中构造一个表达式:
enum { X };
static_assert(X != X, "...");
具体用例:我有一个类模板 List这是用子类型定义的 head和 tail如果非空,如果使用这些子类型如果它是空的,应该给出一个错误:
template<typename...>
struct List;
// empty list:
template<>
struct List<> {
struct head { static_assert(false, "Attempt to access the head of an empty list."); };
struct tail { static_assert(false, "Attempt to access the tail of an empty list."); };
};
// non-empty list:
template<typename Head, typename ...Tail>
struct List<Head, Tail...> {
typedef Head head;
typedef List<Tail...> tail;
};
如果我只是忽略类型 head和 tail ,当访问例如列表的第三个元素,大小为 2,代码为 List<int,int>::tail::tail::head给出不太好的消息(g++ 4.7.2):'head' is not a member of 'List<int>::tail {aka List<>}'
最佳答案
// empty list:
template<typename... Args>
struct List {
struct head {static_assert(sizeof...(Args) != 0, "Attempt to access the head of an empty list."); };
struct tail {static_assert(sizeof...(Args) != 0, "Attempt to access the tail of an empty list."); };
};
// non-empty list:
template<typename Head, typename ...Tail>
struct List<Head, Tail...> {
typedef Head head;
typedef List<Tail...> tail;
};
编辑:这个问题实际上涉及 C++ 模板工作方式的三个方面:
- (§14.7.1 [temp.inst]/p1) Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions ... of the class member functions, member classes, [...].
- (§14.7.1 [temp.inst]/p11) An implementation shall not implicitly instantiate ... a member class...of a class template that does not require instantiation.
- (§14.6 [temp.res]/p8) If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.
3) 表示 static_assert 表达式必须依赖于模板参数,否则会为模板生成“无有效特化”并且程序格式错误,编译器可以自由报告错误(尽管他们不必须)。在上面的代码中,可以为第一个模板生成一个有效的特化,但是由于部分特化,这样的特化永远不会被使用。
上面给出的解决方案也依赖于1)和2)。 1) 规定隐式实例化模板特化仅实例化成员类的声明(不是定义),并且 2) 明确禁止编译器尝试实例化 head 或tail 如果仅使用隐式实例化的 List<> 。请注意,如果您使用 List<> 显式实例化 template struct List<>;,则此规则不适用。
leemes 答案中的解决方案有效,因为 typedef 不需要完整类型,因此不会触发 1) 下 SubTypeErrorMessage<> 的隐式实例化,并且在 static_assert 中使用模板参数绕过 3),作为有效可以为该模板生成特化(即 SubTypeErrorMessage)。
值得注意的是,在这两种情况下,实例化规则意味着使用 SubTypeErrorMessage<true> 或 List<>::head 仍然是合法的,只要您不以需要完整类型的方式使用它们。因此像 TypeC::subtype 这样的东西是有效的,虽然完全没有意义,因为你没有办法真正调用那个函数。但是,如果您根本不定义 int f(List<>::head & ) { return 0; },编译器将在此代码上报告一个(可能是神秘的)错误。所以这是更漂亮的错误消息的权衡:)
关于c++ - 访问未定义子类型时的自定义编译错误消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24420340/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我可以得到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)