短路运算符在enable_if
Short Circuiting Operators in an enable_if
我想编写一个需要array<int, 3>
或int[3]
的模板化函数。我试图在enable_if
中捕捉到这一点:
template<typename T>
enable_if_t<is_array_v<T> && extent_v<T> == 3U || !is_array_v<T> && tuple_size<T>::value == 3U> foo(const T& param) {}
不幸的是,对于int[3]
,tupple_size
没有定义,这导致模板在评估短路之前无法编译。
我也尝试使用conditional
来执行此操作,但这具有相同的问题,即在考虑条件之前确保两个选项都对T
有效。
我知道我可以通过专业化来做到这一点。但是代码在函数主体中完全相同。我讨厌在实现相同时我专门从事的事实。
有没有办法在评估条件之前强制短路?
利用非数组类型的extent<T>
为零,因此是伪造的,并且disjunction
从列表中的第一个真实类型派生出短路:
template<typename T>
enable_if_t<disjunction<extent<T>, tuple_size<T>>::value == 3U> foo(const T& param) {}
这可能太聪明了。请注意,您不能在此处使用disjunction_v
。
conditional
也应该工作得很好。诀窍是在选择正确的类型之前不要要求::value
:
template<typename T>
enable_if_t<conditional_t<is_array_v<T>, extent<T>, tuple_size<T>>::value == 3U>
foo(const T& param) {}
简而言之,不,模板替换必须始终有效。只定义一个特定的模板来匹配数组可能会更容易:
template <typename T>
struct IsArrayInt3 { enum: bool { value = false }; };
template <>
struct IsArrayInt3<int[3]> { enum: bool { value = true }; };
template <>
struct IsArrayInt3<std::array<int, 3>> { enum: bool { value = true }; };
我会建议另一种方法:2 个重载(总是更喜欢重载而不是模板专用化(,调用包含通用代码的公共函数:
namespace detail
{
template <class T>
auto foo_impl(const T& a)
{
// common code
}
}
template <class T>
auto foo(const std::array<T, 3>& a)
{
detail::foo_impl(a);
}
template <class T>
auto foo(const T(&a)[3])
{
detail::foo_impl(a);
}
这清晰、轻松,并避免了代码重复。
另一种方法是创建自己的特征:
template <class T, std::size_t Size>
struct my_is_array : std::false_type
{};
template <class T, std::size_t Size>
struct my_is_array<std::array<T, Size>, Size> : std::true_type
{};
template <class T, std::size_t Size>
struct my_is_array<T[Size], Size> : std::true_type
{};
template<typename T>
std::enable_if_t<my_is_array<T, 3>::value> foo(const T& param) {}
或者(我实际上更喜欢这个(:
template <class T>
struct array_size_or_zero : std::integral_constant<std::size_t, 0>
{};
template <class T, std::size_t Size>
struct array_size_or_zero<std::array<T, Size>> : std::integral_constant<std::size_t, Size>
{};
template <class T, std::size_t Size>
struct array_size_or_zero<T[Size]> : std::integral_constant<std::size_t, Size>
{};
template<typename T>
std::enable_if_t<array_size_or_zero<T>::value == 3> foo(const T& param) {}
小心!!:foo
必须通过引用具有参数,否则数组将衰减为指针。
相关文章:
- 我的简单if-else语句是如何无法访问的代码
- 如何将enable-if与模板参数和参数包一起使用
- 无论条件是否为true,if总是在c++中执行
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 如何删除peer if else分支中的冗长句子
- 我似乎对if/else的基本语句有问题:/
- if数组上的随机数
- 将按位if条件转换为普通if条件
- If语句在c++中被忽略
- 比较if语句中的数组值和int值
- 使用if-else将数字转换为单词
- 为什么简单的算术减法在"if"条件下不起作用?
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- SFINAE with boost enable if