如何使用布尔模板参数启用成员函数?

How to enable member function using boolean template parameter?

本文关键字:成员 函数 启用 参数 何使用 布尔模      更新时间:2023-10-16

我希望一个类有两个不同的push实现,并根据布尔模板参数进行选择。我尝试使用本答案中所述的 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"的错误,我不明白为什么。虽然我的代码与链接答案中的代码不完全相同,但它看起来非常相似,我无法发现关键差异。

我还尝试使用类似于此答案中建议的语法,但它也不起作用(错误是"无法重新声明类成员"):

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 */ } 

我怎样才能做到这一点?

首先,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 */ } 

作为替代方案:

  • C++17if 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>{});
    }
    };