【问题标题】:how to check if function exists如何检查函数是否存在
【发布时间】:2014-02-18 09:27:02
【问题描述】:

我想实现我自己的 std::make_unique 函数,该函数是 std 命名空间的一部分。我知道这个辅助函数已添加到 C++14,但我在 C++11 中没有。所以,我想用一些 C++11 模板魔法(找不到任何带有宏的选项)来检查它是否存在于 std 命名空间中,以及它是否没有自己定义。那可能吗?我什至不知道从哪里开始。

【问题讨论】:

  • 从程序本身内部是不可能的。但是,您可以使用autoconf 或cmake 等工具在构建之前检查函数,并根据检查结果定义预处理器宏。
  • 为什么你认为它应该在std?
  • 您可能需要考虑始终调用您自己的函数,并将该函数调度到 make_uniq 或您自己的函数,具体取决于 std::make_uniq 是否存在(通过 sfinae 检测)
  • @MSalters 因为我希望能够使用std::make_unique,而不是我自己的东西。 @PlasmaHH 在您发表评论后,我正在考虑改变我对这个特定代码设计的“信念”。

标签: c++ templates c++11 macros


【解决方案1】:

您不能将新函数添加到 ::std 命名空间。您只能添加现有模板的特化,即使那样也只能添加到您自己的类型。

【讨论】:

  • 是什么阻止我做namespace std { foo(); }?
  • 你不被允许这样做并不意味着你不能。
  • @Paranaix:你的程序变得不符合标准,编译器检测到它可能会拒绝它,或者它可能会做任何事情......@丹尼尔:是的, cannot 以斜体显示是有原因的。
  • @DanielFrey 请参阅stackoverflow.com/q/8513417/819272 当然,除非编译器检查std 中允许的名称的整个列表,否则您可能会侥幸成功
  • @TemplateRex 我可以想到很多方法,如果没有主动检查,这可能会导致坏事发生。该功能是在没有更新版本的情况下添加的,可能存在一些差异。编译器将std "headers" 实现为非纯 C++ 代码以用于优化目的,因此当您 std:: 时,您正在与仅 看起来 像 C++ 命名空间的东西进行交互。阅读您的代码的人会在 4 年后看到 std::make_unique,并认为它是 C++1y 的 make_unique,但随着时间的推移标准发生了变化,现在您的代码无法维护。
【解决方案2】:

最好的办法是使用标准的 __cplusplus 宏,对于 C++11,它是 201103L。对于 C++14 及以后的版本,这将是不同的值。

【讨论】:

    【解决方案3】:

    这不是一个真正的答案,但我想指出委员会正在考虑(参见n3694)一个通用问题:程序员如何确定一个实现是否具有特定功能(例如std::make_unique) ?

    目前,我们最好的是宏__cplusplus(根据Bathsheba 的post),但正如n3694 中所解释的那样,这并不能提供程序员可能需要的细粒度。 (OP的问题就是这种需求的一个例子。)

    【讨论】:

      【解决方案4】:

      介绍std::make_unique自己是未定义的行为,句号。没有安全的方法可以做到这一点。最重要的是,这也是不可取的——你获得的优势很小,维护和代码可理解性成本很高。

      更重要的是,您的 make_unique 可能与发布的内容不匹配,因此您的代码将具有奇怪的版本依赖性。

      更好的计划是在您自己的实用程序命名空间中的其他位置定义您自己的make_unique。如果 C++1y 处于活动状态,您可以 using std::make_unique 导入它而不是您自己的 make_unique。

      这使您的代码标准符合要求。 utility::make_unique 的用户也应该清楚,它不能保证与 C++1y 的 make_unique 相同。

      这还可以让您解决检测std::make_unique 的问题,直到它被标准化,然后确定它是否与您最终实现的接口匹配。

      【讨论】:

        【解决方案5】:
        #include <memory> // std::shared_ptr, std::unique_ptr
        
        // C++11 check doesn't work in Visual Studio 2013/2015 properly because they are not fully C++11 compliant.
        // https://connect.microsoft.com/VisualStudio/feedback/details/763051/a-value-of-predefined-macro-cplusplus-is-still-199711l
        #ifndef WIN32
        // C++11 Check
        #if __cplusplus < 201103L
        #error This library needs at least a C++11 compliant compiler.
        #endif // >= C++11
        #endif // WIN32
        
        
        namespace std {
        
          // Note: despite not being even C++11 compliant, Visual Studio 2013 has their own implementation of std::make_unique.
        #ifndef WIN32
        #if (__cplusplus >= 201103L && __cplusplus < 201402L)
          // Define std::make_unique for pre-C++14
          template<typename T, typename... Args> inline unique_ptr<T> make_unique(Args&&... args) {
            return unique_ptr<T>(new T(forward<Args>(args)...));
          }
        #endif // C++11 <= version < C++14
        #endif // WIN32
        
        } // namespace std
        

        【讨论】:

          猜你喜欢
          • 2015-07-24
          • 2014-01-14
          • 2010-11-05
          • 2017-07-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-22
          相关资源
          最近更新 更多