假设我有以下定义嵌套类的模板类:
template <typename T>
struct foo {
struct bar { };
};
假设我正在编写代码的环境也有以下帮助程序类,它应该专门用于需要特殊处理的任何类型:
template <typename T>
struct maybeChangeType { using type = T; } /* default: same type */
我怎样才能专攻maybeChangeType对于 foo<T>::bar ?专门针对 foo<int>::bar 很容易,但是 foo将与 100 多种不同的 T 一起使用所以这不是一个真正的选择。
注意:请在将此问题标记为重复之前仔细阅读。这个问题不是询问一般如何专门化(例如 Understanding templates in c++ ),或者如何声明 friend ,甚至如何声明模板的 friend 。它询问如何为模板类的非模板嵌套成员声明友元(如标题所述)。
尝试以“正常”方式定义特化是行不通的,因为 foo<T>::bar不是可推导的上下文(不好的迹象:它需要在前面 typename):
/* error: template parameters not deducible in partial specialization */
template <typename T>
struct maybeChangeType<typename foo<T>::bar>;
将特化声明为友元也会产生编译错误:
template <typename T>
struct foo {
struct bar {
/* errors:
* - class specialization must appear at namespace scope
* - class definition may not be declared a friend
*/
template <>
friend struct maybeChangeType<bar> { using type=T; };
};
};
以上错误清楚地表明这些 friend 的实际定义必须出线:
template <typename T>
struct foo {
struct bar {
friend struct maybeChangeType<bar>;
};
};
但现在我们回到了起点:任何为 foo<T>::bar 定义特化的尝试将失败,因为它使用 bar在不可推导的上下文中。
注意:我可以通过提供内联友元重载来解决函数的问题,但这对类没有帮助。
注意:我可以通过将内部类移出命名空间范围来解决这个问题,但这会严重污染命名空间(很多内部类用户实际上没有业务可玩)并使实现复杂化(例如,他们会不再能够访问其封闭类的私有(private)成员,并且 friend 声明的数量会激增)。
注意:我理解为什么允许任意特化名称 foo<T>::bar 是危险的/不可取的(如果 foo<T> 有 using bar = T 会怎么样),但在这种情况下 bar实际上是 foo 确实定义的类(甚至不是模板!),因此不应该有任何 ODR 毛羽或特化会影响其他(非预期)类型的风险。
想法?
最佳答案
作为一种侵入式解决方案,可以使用函数进行类型编程(元编程)。您可以将类型函数编写为友元函数:
template<typename T> struct type_t { using type = T; };
template <typename T>
struct foo {
struct bar {
friend constexpr auto maybeChangeType_adl(type_t<bar>) -> type_t<T>
{ return {}; }
};
};
替换type_t<T>与任何 type_t<my_type_function_result> .定义此函数不是必需的,但有时很方便,例如用于常量表达式中的计算。 type_t可以使用比较运算符进行增强,以替换 std::is_same<A, B>带中缀 a == b例如。类型type_t<T>使用而不是 T直接有两个原因:
maybeChangeType_adl 的定义, 有必要
构造一个返回类型的对象。在 C++14 中,我会使用变量模板来实现这个功能:
template<typename T> constexpr auto type = type_t<T>{};
// ...
friend constexpr auto maybeChangeType_adl(type_t<bar>) { return type<T>; };
虽然这失去了一些对称性(参数与返回类型)。
无论哪种情况,都可以查询类型如下:
template<typename T> using inner_type = typename T::type;
template<typename T> using maybeChangeType =
inner_type<decltype(maybeChangeType_adl(type_t<T>{}))>;
回退函数 maybeChangeType可以提供镜像 OP 中的主模板:
template<typename T> auto maybeChangeType(type_t<T>) -> type_t<T> { return {}; }
或者,您专攻 maybeChangeType maybeChangeType_adl 存在的类模板功能:
template<typename T, typename = void>
struct maybeChangeType { using type = T; };
template<typename T>
struct maybeChangeType<T, void_t<decltype(maybeChangeType_adl(type_t<T>{}))>>
{ using type = inner_type<decltype(maybeChangeType_adl(type_t<T>{}))>; };
关于c++ - 如何为模板类中定义的类定义 friend ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32144877/
我正在尝试设置一个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
我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我想向我的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
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>