草庐IT

c++ - 这个 SFINAE 模式有名字吗?

coder 2024-02-04 原文

在“太阳底下没有新鲜事”的规则下运作,我怀疑我是第一个想出这个把戏的人。我想我最终会偶然发现一些在线记录它的东西,但我还没有,所以我想我会问。

它的目的是在不使用派生类的情况下有选择地启用某些相关的功能。

这个图案有名字吗?有没有人有任何关于这种模式或类似运作模式的有用信息?

template<typename T, size_t N>
class Point {
public:
  template<size_t P, typename T2=void>
  using Enable2D = typename std::enable_if<P == 2 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable3D = typename std::enable_if<P == 3 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable4D = typename std::enable_if<P == 4 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable2DOrHigher = typename std::enable_if<P >= 2 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable3DOrHigher = typename std::enable_if<P >= 3 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable4DOrHigher = typename std::enable_if<P >= 4 && N == P, T2>::type;

  //Example use cases
  template<size_t P=N>
  static Enable2D<P, Point> withAngle(T angle, T magnitude = 1);
  template<size_t P=N>
  static Enable3D<P, Point> fromAngles(T psi, T theta, T magnitude = 1);

  template<size_t P=N>
  Enable2DOrHigher<P, T> const& x() const;
  template<size_t P=N>
  Enable2DOrHigher<P, T> const& y() const;
  template<size_t P=N>
  Enable2DOrHigher<P> setX(T const& t);
  template<size_t P=N>
  Enable2DOrHigher<P> setY(T const& t);

  template<size_t P=N>
  Enable3DOrHigher<P, T> const& z() const;
  template<size_t P=N>
  Enable3DOrHigher<P> setZ(T const& t);

  template<size_t P=N>
  Enable4DOrHigher<P, T> const& w() const;
  template<size_t P=N>
  Enable4DOrHigher<P> setW(T const& t);
};

最佳答案

我不会将其称为模式,但它是一种已知技术。

通常被称为条件接口(interface) 这种技术主要解决编译时切换机制来打开和关闭类接口(interface)的问题。整个过程提供的工具还可以切换成员的存在(因此术语条件编译 诞生)。

该技术或多或少地按照您建议的方式实现(尽管在 c++11 之前缺少别名模板不是问题),通常的问题是繁重、困惑、困惑和“丑陋”的模板机械样板代码。

解决这个问题,A.亚历山大列斯库 gave a presentation关于这个话题。最初有一小部分提到对这种技术的需求:

子弹说

  • 此函数仅适用于数字

指的是您的技术以及需要编译时条件来切换函数的存在(条件接口(interface))。

谈话继续到新语言功能的提案。既然我们都发明了几次轮子,他说,为什么不使用一种新的语言语法,这将使我们能够执行这样的事情。他的joint workH. Sutter 生成了 static if 一个编译时切换器,它将消除您提到的解决方法的需求。一个简单的用法是

template<int D>
struct Vector
{
    double coordinates[D];
    static if ( D ) {
        double x() { return coordinates[0]; }
    }
    static if ( D > 1 ) {
        double y() { return coordinates[1]; }
    }
    static if ( D > 2 ) {
        double z() { return coordinates[2]; }
    }
};

好吧,也许这不是最聪明的用法,但我想我正在传达这个想法。

现在在对面,B. Stroustrup 发表了 paper在了解 static if 正在解决的问题后,他解释了为什么这是一个有缺陷的概念(双关语意:))并且它的采用对语言来说将是一场灾难(哎哟!)。

这是我的两分钱,从这个“对话”中参与者的水平来看,我想得到一些关于他们站在哪一边的反馈,或者如果他们是标准化过程的一部分,那么什么会他们正在投票。

关于c++ - 这个 SFINAE 模式有名字吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23073931/

有关c++ - 这个 SFINAE 模式有名字吗?的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. ruby-on-rails - environment.rb 中设置的常量在开发模式中消失 - 2

    了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl

  9. ruby - 这个 ruby​​ 注入(inject)魔术是如何工作的? - 2

    我今天看到了一个ruby​​代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem

  10. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

随机推荐