英文:
Using std::enable_if with complex predicates
问题
使用 typename std::enable_if<IsVector<T>::value || IsList<T>::value, void>::type
作为约束条件时,它可以正常工作。如果使用 typename std::enable_if<IsVectorOrList<T>::value>::type
,编译器会报错。
如何让它正常工作呢?
英文:
Having to use C++14 I'd like to use std::enable_if to make a function only being available given certain constraints. I do so using or_<>
taken from the libc header type_traits
instead of std::disjunction
(no C++17 available in my environment) in order to move the constraint logic into a separate construct.
However, I seem to be missing something, because I can't manage to get it to compile.
My code:
#include <type_traits>
#include <iostream>
#include <vector>
#include <list>
template <typename T>
struct IsVector : public std::false_type {};
template <typename T>
struct IsVector<std::vector<T>> : public std::true_type {};
template <typename T>
struct IsList : public std::false_type {};
template <typename T>
struct IsList<std::list<T>> : public std::true_type {};
// taken from libc type_traits
template <bool, typename, typename>
struct conditional;
template <typename...>
struct or_;
template <>
struct or_<> : public std::false_type {};
template <typename _B1>
struct or_<_B1> : public _B1 {};
template <typename _B1, typename _B2>
struct or_<_B1, _B2> : public conditional<_B1::value, _B1, _B2>::type {};
template <typename _B1, typename _B2, typename _B3, typename... _Bn>
struct or_<_B1, _B2, _B3, _Bn...> : public conditional<_B1::value, _B1, or_<_B2, _B3, _Bn...>>::type {};
// ---
template <typename T>
struct IsVectorOrList : public or_<IsVector<T>, IsList<T>>::type {};
template <typename T>
typename std::enable_if<IsVector<T>::value || IsList<T>::value, void>::type
// replacing with this line does not work
//typename std::enable_if<IsVectorOrList<T>::value, void>::type
foo(const T& list)
{
for (const auto& item : list)
{
std::cout << item << std::endl;
}
}
int main()
{
foo(std::vector<int>{17, 42});
foo(std::list<float>{1.0, 2.71, 3.14});
}
When using typename std::enable_if<IsVector<T>::value || IsList<T>::value, void>::type
as constraint it works fine. If I use typename std::enable_if<IsVectorOrList<T>::value>::type
the compiler complains:
traits.cpp:32:8: error: invalid use of incomplete type ‘struct conditional<true, IsVector<std::vector<int> >, IsList<std::vector<int> > >’
32 | struct or_<_B1, _B2> : public conditional<_B1::value, _B1, _B2>::type {};
| ^~~~~~~~~~~~~
traits.cpp:20:8: note: declaration of ‘struct conditional<true, IsVector<std::vector<int> >, IsList<std::vector<int> > >’
20 | struct conditional;
| ^~~~~~~~~~~
How do I make it work?
答案1
得分: 2
以下是翻译好的部分:
"// taken from libc type_traits" -> "// 从 libc type_traits 中获取"
"The code declares conditional
, but that class isn't defined anywhere in the posted snippet." -> "这段代码声明了 conditional
,但该类在发布的片段中没有定义。"
"Removing those lines and using std::conditional
the code works." -> "删除这些行并使用 std::conditional
代码可以正常工作。"
英文:
Here:
// taken from libc type_traits
template <bool, typename, typename>
struct conditional;
The code declares conditional
, but that class isn't defined anywhere in the posted snippet.
Removing those lines and using std::conditional
the code works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论