如何使用布尔模板参数启用成员函数?
How to enable member function using boolean template parameter?
我希望 class 有两个不同的 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下得到了"cannot specialize a function push
within class scope"的错误,我不明白为什么。虽然我的代码与链接答案中的代码不完全一样,但看起来非常相似,我看不出关键的区别。
我也尝试使用类似于 中建议的语法,但它也不起作用(错误是 "class member cannot be redeclared"):
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 */ }
备选方案:
if constexpr
在 C++17 中:
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>{});
}
};
我希望 class 有两个不同的 push
实现,并根据布尔模板参数进行选择。我尝试使用
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下得到了"cannot specialize a function push
within class scope"的错误,我不明白为什么。虽然我的代码与链接答案中的代码不完全一样,但看起来非常相似,我看不出关键的区别。
我也尝试使用类似于
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 */ }
备选方案:
if constexpr
在 C++17 中: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>{}); } };