有没有办法检查class有一个 typedef这甚至适用于 private typedef ?
以下代码在 VS2013 中有效,但在 ideone's gcc 上失败
template<typename T>
struct to_void
{
typedef void type;
};
class Foo
{
typedef int TD;
};
template <typename T, typename dummy = void>
struct has_TD : std::false_type {};
template <typename T>
struct has_TD<T, typename to_void<typename T::TD>::type > : std::true_type{};
int main()
{
std::cout << std::boolalpha << has_TD<Foo>::value << std::endl;
}
编辑 - 我为什么要这个
我有自定义序列化系统,可以序列化任意类型。当它必须表现不同时(例如字符串),它有几个重载。对于其余类型,它只是将值写入内存。如果我有组合类型,有时我也可以只写入内存(保存和加载发生在相同的体系结构上,使用相同的编译器编译,因此填充将相同,等等)。例如,此方法对 POD 类型( std::is_pod 特征)有效,但所有 POD 类型只是所有类型的子集,支持此序列化。
所以我基本上有模板函数 write<T>只写sizeof(T) bytes (raw-serialization)...但我不希望这个被错误地调用,我希望用户在他们的类中明确地说:“这个类/结构可以被原始序列化”)。我这样做的方式是一个宏 ALLOW_RAW_SERIALIZE它定义了一些可以通过 trait 检查的 typedef。如果类MyClass不包含 typedef,调用 write(myClassInstance)会产生编译错误。
基本决定类是否可以被原始序列化的是它的成员(没有反射,成员不能被自动枚举和检查,所以用户必须提供这样的信息)。典型的类看起来像这样:
class
public
ctor-dtor
methods
private
methods
members
我希望用户允许写入 ALLOW_RAW_SERIALIZE尽可能靠近成员,因此当他们更改某些成员时,忘记更新的机会较小 ALLOW_RAW_SERIALIZE (删除它。当它不再有效时)
所以这就是为什么我要检查 private typedef
因为它是反射的替代品并且需要整个类型并编写它,所以我不会像破坏封装那样对它感到失望......
最佳答案
更新:
好的,做了一点研究。
仅供引用,ideone 未编译的 [可能] 原因是您正在做的事情需要 -std=c++11 [或更高版本]。在添加之前我遇到了类似的错误。但是,我不得不使用 clang++,因为如果 TD 是 private,g++ 仍然有编译问题。
但是,我不确定这是否有效,因为唯一打印 true 的组合是 TD 是否公开。所有其他的 public/private 以及将 TD 更改为 TF 都会产生错误。也许 VS2013 工作 [为什么?],但其他两个编译器在编译或运行时结果方面存在问题 -- YMMV。
你正在做的事情的基础是 std::integral_constant [自 c++11 起]。对于您正在做的事情,似乎没有标准推导。即来自 http://www.cplusplus.com/reference/type_traits/integral_constant/类型特征列表 [左侧] 没有与您的用例 [AFAICT] 匹配的内容。
Boost.TypeTraits 也没有任何匹配项 [再次强调,AFAICT]。
来自 Andrei Alexandrescu 的书:“Modern C++ Design: Generic Programming and Design Patterns Applied”,第 2.10 节类型特征:
Usually, you will write your own trait templates and classes as your generic code needs them. Certain traits, however, are applicable to any type. They can help generic programmers to tailor template code better to the capabilities of a type.
因此,如果您愿意,自己动手“没问题”。
但是,即使是他所说的 [来自 Loki] 的 TypeTraits,也没有任何与您正在做的相匹配的东西。
既然std和Boost都没有任何东西,那么问题就变成了“什么是标准?” [从你的角度]。某处可能有“fludger”c++ traits 库有一个实现,但那会被认为是“标准”吗? YMMV
但是,一两个问题:
为什么要这样做?它有什么用?基类中 protected typedef 怎么样?
而且,这似乎需要了解类的私有(private)部分,这不会违反“数据隐藏”或封装 [没有某种 friend 声明] ?
所以,如果最后一个问题是真的,[IMO] 可能的答案是没有标准的方法来做到这一点,因为这不是一个应该的事情在标准库中执行。
旁注:这是被否决的部分(在我 [真正] 理解这个问题之前)。我相信我已经在上面证明自己无罪了。所以,请忽略下面的答案。
当您使用 class 时,默认 可见性是 private。对于 struct,它是public。
所以,要么:
struct Foo
或者:
class Foo
{
public:
typedef int TD;
};
当然,这是假设您希望 TD public
关于c++ - 检查类是否具有 typedef(私有(private)或其他)的特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34586624/
类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
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
为了将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
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden