【问题标题】:Make C++ fail compilation on specific instantiation of template function使 C++ 在模板函数的特定实例化时编译失败
【发布时间】:2017-08-15 21:08:36
【问题描述】:

我正在开发一个具有模板功能的项目:

template <class T> 
T foo<T>(T val) { return someFunc(val); }

template <>
bool foo<bool>(bool val) { return otherFunc(val); };

现在,我有一个课程Bar,我不想接受它作为输入。事实上,我希望它生成一个易于发现的编译错误。问题是,如果我这样做:

template <>
Bar foo<Bar>(Bar val) { static_assert(false,"uh oh..."); }

每次编译都会失败。我找到了https://stackoverflow.com/a/3926854/7673414,它说我需要引用模板类型,否则总是会发生静态断言。问题是我这里没有模板类型。如果我这样做:

template< typename T >
struct always_false { 
    enum { value = false };  
};

template <>
Bar foo<Bar>(Bar val) { static_assert(always_false<Bar>::value,"uh oh..."); }

那么它也总是无法编译。有没有办法确保 Bar 类型的模板实例化总是导致编译错误?

【问题讨论】:

    标签: c++ c++11 templates template-specialization


    【解决方案1】:

    由于foo 是一个完整的特化,它总是会被编译,并且总是会调用静态断言。

    但是,有一个easier way

    template <>
    Bar foo<Bar>(Bar val) = delete;
    

    这会说这个特定的版本被删除了,并且不能被调用。

    【讨论】:

    • 这很好,但我会删除 d-tor 而不必删除所有各种 c-tor。
    • @YehezkelB。这是一个函数模板,而不是类模板。您可以删除函数模板特化,而不仅仅是构造函数和析构函数。
    【解决方案2】:

    另一种方法是仅在类型与Bar不同时启用模板(非专用版本)

    template <class T> 
    typename std::enable_if< ! std::is_same<T, Bar>::value, T>::type foo<T>(T val)
     { return someFunc(val); }
    

    如果你可以使用C++14,可以使用std::enable_if_t进行简化

    template <class T> 
    std::enable_if_t< ! std::is_same<T, Bar>::value, T> foo<T>(T val)
     { return someFunc(val); }
    

    【讨论】:

      【解决方案3】:

      您可以使用std::is_same 来满足您的要求。

      template <class T> 
      T foo<T>(T val)
      {
         // Make sure T is not Bar
         static_assert(std::is_same<T, Bar>::value == false, "uh oh...");
         return someFunc(val);
      }
      

      【讨论】:

      • 能否请您为static_assert 添加缺少的)
      【解决方案4】:

      如果你使用的是c++17,你可以用constexpr if把所有东西放在一起:

      template< typename T >
      auto foo( T val )
      {
          static_assert( !std::is_same_v<T,Bar> );
      
          if constexpr( std::is_same_v<T,bool> )
          {
              return  other_func( val );
          }
          else
          {
              return some_func( val );
          }
      
      }
      

      然后你可以在第一行static_assert,不用担心模板特定实例化编译失败的痛苦。

      https://wandbox.org/permlink/PpR6G0gcvMRoxhhZ 上提供了一个实时示例

      【讨论】:

        猜你喜欢
        • 2018-06-10
        • 1970-01-01
        • 1970-01-01
        • 2012-02-15
        • 1970-01-01
        • 2015-02-09
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        相关资源
        最近更新 更多