【问题标题】:How to enable member function using boolean template parameter?如何使用布尔模板参数启用成员函数?
【发布时间】:2017-12-22 03:29:12
【问题描述】:

我希望一个类有两种不同的push 实现,并根据布尔模板参数进行选择。我尝试使用this answer 中描述的 SFINAE 原则,如下所示:

template<class T, bool foo=true>
class Bar {
  template <>
  typename std::enable_if<foo>::type
  push(const T& value) { /* one implementation */}

  template <>
  typename std::enable_if<!foo>::type
  push(const T& value) { /* another implementation */ } 
}

但是,我在 gcc 下收到“无法在类范围内专门化函数 push”的错误,我不明白为什么。虽然我的代码与链接答案中的代码不完全相同,但看起来非常相似,我无法发现关键区别。

我也尝试使用类似于this answer 中建议的语法,但它也不起作用(错误是“无法重新声明类成员”):

  template <bool enable=foo>
  typename std::enable_if<enable>::type
  push(const T& value) { /* one implementation */}

  template <bool enable=!foo>
  typename std::enable_if<enable>::type
  push(const T& value) { /* another implementation */ } 

我怎样才能做到这一点?

【问题讨论】:

    标签: c++ templates sfinae


    【解决方案1】:

    首先,SFINAE 使用函数模板重载;所以你应该采用第二种方法。但是您声明了两个具有相同签名的重载;注意模板参数的默认参数不属于签名。

    改成

    template <bool enable=foo>
    typename std::enable_if<enable>::type
    //                      ~~~~~~
    push(const T& value) { /* one implementation */}
    
    template <bool enable=foo>
    typename std::enable_if<!enable>::type
    //                      ~~~~~~~
    push(const T& value) { /* another implementation */ } 
    

    【讨论】:

      【解决方案2】:

      作为替代方案:

      • C++17 中的if constexpr

        template<class T, bool foo=true>
        class Bar {
        public:
            void push(const T& value) {
                if constexpr(foo) {
                    /* one implementation */
                } else {
                    /* another implementation */
                }
            }
        };
        
      • 标签调度:

        template<class T, bool foo=true>
        class Bar {
            void push_impl(const T& value, std::true_type) {
                /* one implementation */
            } 
            void push_impl(const T& value, std::false_type) {
                /* another implementation */
            }
        
        public:
            void push(const T& value) {
                push_impl(value, std::integral_constant<bool, foo>{});
            }
        };
        

      【讨论】:

      • 太棒了。感谢您提供替代选项。我相信我会在某个时候发现这些有用的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      • 2018-12-28
      • 2020-07-08
      相关资源
      最近更新 更多