array/vector 的 C++ SFINAE
C++ SFINAE for array/vector
我想制作一个仅由容器使用的重载运算符 << (array/vector)。
我有以下模板:
namespace reachability {
template <typename Container>
ostream& operator<<(ostream& out, const is_container<Container>(&container)) {
string result = "{";
for (values_t elem : container) {
result += std::string(elem) + ",";
}
std::operator<<(out, result.substr(0, result.length() - 1) + "}");
return out;
}
struct values_t {
string type;
operator std::string() const { return type; }
};
template<typename T, typename _ = void>
struct is_container : std::false_type {};
template<typename... Ts>
struct is_container_helper {};
template<typename T>
struct is_container<
T,
std::conditional_t<
false,
is_container_helper<
typename T::value_type,
typename T::size_type,
typename T::allocator_type,
typename T::iterator,
typename T::const_iterator,
decltype(std::declval<T>().size()),
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end()),
decltype(std::declval<T>().cbegin()),
decltype(std::declval<T>().cend())
>,
void
>
> : public std::true_type{};
}
它用于:
reachability::values_t vals[5];
int main(int argc, char** argv)
{
vals[0].type = "zoo";
vals[1].type = "foo";
vals[2].type = "loo";
vals[3].type = "koo";
vals[4].type = "moo";
/*elements_t elems = { space::half };*/
reachability::operator<<(cout, vals);
return 0;
}
但是我得到一个错误,没有重载运算符的实例与参数列表匹配。
如果我把operator的模板改成:
也会出现同样的问题
ostream& operator<<(ostream& out, const Container (&container)[])
我只是设法让它工作:
ostream& operator<<(ostream& out, const Container (&container))
如果你想在函数声明时出现编译时错误,而不是在实例化该函数模板的主体时,你可以通过添加另一个语法检查的模板参数来制作 SFINAE,如果它没有有任何意义,编译器会通过说 no matching function for call ...:
来告诉你
template <
typename Container,
std::enable_if_t< is_container<Container>::value |
std::is_array_v<Container> >* = nullptr>
ostream& operator<<(ostream& out, const Container&container ) {
如您所见,添加了第二个模板参数,只有当 Container
是某种支持 [=14 的 class 类型时,它才会是 void* = nullptr
(这是有效语法) =]/end
/size
等或者是内置数组类型(T []
)。否则,编译器会抱怨它无法为声明 type* = nullptr
.
获取 type
std::vector<reachability::values_t> v;
std::list<reachability::values_t> l;
std::pair<int,int> p;
reachability::operator<<(cout, vals); // OK
reachability::operator<<(cout, v); // OK
reachability::operator<<(cout, l); // OK
reachability::operator<<(cout, p); // Wrong, compile-time error, no match ...
如果您想使用您定义的 is_container
,请使用
template<
typename Container,
std::enable_if_t<is_container<Container>::value, int>= 0>
ostream& operator<<(ostream& out, const Container &container) {}
enable_if_t 将根据布尔值 is_container<Container>::value
隐藏函数以避免重载解析。
请注意,您对 is_container
的定义将接受集合
std::vector<reachability::values_t> vals(5);
但不是数组
reachability::values_t vals[5];
我想制作一个仅由容器使用的重载运算符 << (array/vector)。
我有以下模板:
namespace reachability {
template <typename Container>
ostream& operator<<(ostream& out, const is_container<Container>(&container)) {
string result = "{";
for (values_t elem : container) {
result += std::string(elem) + ",";
}
std::operator<<(out, result.substr(0, result.length() - 1) + "}");
return out;
}
struct values_t {
string type;
operator std::string() const { return type; }
};
template<typename T, typename _ = void>
struct is_container : std::false_type {};
template<typename... Ts>
struct is_container_helper {};
template<typename T>
struct is_container<
T,
std::conditional_t<
false,
is_container_helper<
typename T::value_type,
typename T::size_type,
typename T::allocator_type,
typename T::iterator,
typename T::const_iterator,
decltype(std::declval<T>().size()),
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end()),
decltype(std::declval<T>().cbegin()),
decltype(std::declval<T>().cend())
>,
void
>
> : public std::true_type{};
}
它用于:
reachability::values_t vals[5];
int main(int argc, char** argv)
{
vals[0].type = "zoo";
vals[1].type = "foo";
vals[2].type = "loo";
vals[3].type = "koo";
vals[4].type = "moo";
/*elements_t elems = { space::half };*/
reachability::operator<<(cout, vals);
return 0;
}
但是我得到一个错误,没有重载运算符的实例与参数列表匹配。
如果我把operator的模板改成:
也会出现同样的问题ostream& operator<<(ostream& out, const Container (&container)[])
我只是设法让它工作:
ostream& operator<<(ostream& out, const Container (&container))
如果你想在函数声明时出现编译时错误,而不是在实例化该函数模板的主体时,你可以通过添加另一个语法检查的模板参数来制作 SFINAE,如果它没有有任何意义,编译器会通过说 no matching function for call ...:
来告诉你template <
typename Container,
std::enable_if_t< is_container<Container>::value |
std::is_array_v<Container> >* = nullptr>
ostream& operator<<(ostream& out, const Container&container ) {
如您所见,添加了第二个模板参数,只有当 Container
是某种支持 [=14 的 class 类型时,它才会是 void* = nullptr
(这是有效语法) =]/end
/size
等或者是内置数组类型(T []
)。否则,编译器会抱怨它无法为声明 type* = nullptr
.
type
std::vector<reachability::values_t> v;
std::list<reachability::values_t> l;
std::pair<int,int> p;
reachability::operator<<(cout, vals); // OK
reachability::operator<<(cout, v); // OK
reachability::operator<<(cout, l); // OK
reachability::operator<<(cout, p); // Wrong, compile-time error, no match ...
如果您想使用您定义的 is_container
,请使用
template<
typename Container,
std::enable_if_t<is_container<Container>::value, int>= 0>
ostream& operator<<(ostream& out, const Container &container) {}
enable_if_t 将根据布尔值 is_container<Container>::value
隐藏函数以避免重载解析。
请注意,您对 is_container
的定义将接受集合
std::vector<reachability::values_t> vals(5);
但不是数组
reachability::values_t vals[5];