c++ - 连续 enable_if 重载调用出错
问题描述
基本上,这个想法是重载operator <<
任何可迭代的东西,比如正确定义 begin() 和迭代器方案的向量、列表和自定义类。
最初,我编写了以下原型
template<template<class, class ...> class Container, class T, class ... Whatever>
std::ostream& operator<<(std::ostream& out, const Container<T, Whatever...>& container) { stuff }
问题是我显然会与任何匹配模板定义并且已经重载的东西发生冲突<<
,例如std::string
. 所以,如果我写cout << string { "Hello" }
,它是模棱两可的。我明白为什么。
因此,这个想法是当且仅当尚未定义 operator<< 时才激活上述重载。我选择通过std::enable_if
以下方式丢弃这种情况:
template<class> struct sfinae_true : std::true_type {};
template<class ToPrint> static auto test_insertion(int) -> sfinae_true<decltype(std::cout << std::declval<ToPrint>())>;
template<class ToPrint> static auto test_insertion(long) -> std::false_type;
template<class ToPrint> struct is_printable : decltype(test_insertion<ToPrint>(0)) {};
template<class ToPrint> using NotPrintable = std::enable_if_t<! is_printable<ToPrint>::value>;
//overload not availlable if operator<< is already defined (avoids ambiguity)
template<template<class, class ...> class Container, class T, class ... Whatever, NotPrintable<Container<T, Whatever...>>* = nullptr>
std::ostream& operator<<(std::ostream& out, const Container<T, Whatever...>& container)
{
//stuff
}
问题是,至少在 C++17 中,我不能打印两次。那是,
vector<int> v1 = {1,2,3,4,5};
vector<int> v2 = {6,7,8};
cout << v1 << endl;
cout << v2 << endl;
编译器告诉我 v2 没有 operator<<... 难以置信,对吧?我不知道为什么,因此不知道如何解决这个问题。
备注:我知道,我可以将原型简单化为template<class Container> std::ostream& operator<<(std::ostrea& out, const Container& c)
,但是让我们说“我不想”。
完整的示例代码复制/粘贴:
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>
template<class> struct sfinae_true : std::true_type {};
template<class ToPrint> static auto test_insertion(int) -> sfinae_true<decltype(std::cout << std::declval<ToPrint>())>;
template<class ToPrint> static auto test_insertion(long) -> std::false_type;
template<class ToPrint> struct is_printable : decltype(test_insertion<ToPrint>(0)) {};
template<class ToPrint> using NotPrintable = std::enable_if_t<! is_printable<ToPrint>::value>;
//overload not availlable if operator<< is already defined (avoids ambiguity)
template<template<class, class ...> class Container, class T, class ... Whatever, NotPrintable<Container<T, Whatever...>>* = nullptr>
std::ostream& operator<<(std::ostream& out, const Container<T, Whatever...>& container)
{
out << "{ ";
auto it = container.begin();
auto it_end = container.end();
if(it != it_end)
{
out << *it;
++it;
}
for(; it != it_end; ++it)
out << " , " << (*it);
out << " }";
return out;
}
using namespace std;
int main()
{
vector<int> v1 = {1,2,3,4,5};
vector<int> v2;
cout << v1 << endl; //prints {1, 2, 3? 4, 5}
cout << v2 << endl; //compile error : no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::vector<int>’)
cout << string {"Hello"} << endl; //works fine
}
错误信息是
error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::vector<int>’)
cout << v2 << endl;
我正在使用 g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 编译,使用命令g++ -o sample sample.cpp
,其中 sample.cpp 是包含上述代码的文件。
解决方案
好吧,基本上,我的编译器版本太旧了。在 gcc 9.3 上,它按预期工作。
话题关闭。(我读到如果我没有足够的代表,我就无法结束自己的话题,而我没有……)
推荐阅读
- sql-server - SQL Server 2012:插入临时表静态值、存储过程的结果和计算值
- php - 3 的雄辩的数据透视表连接到另一个表
- amazon-web-services - AWS S3 最小对象存储 128KB - 同步有意义吗?
- c++ - 从 c++ 方法返回引用
- javascript - sweetalert Ok Popup 后刷新当前页面
- github-api - 使用 github api 在特定存储库中按文件名搜索
- text - 谷歌云上用于 NLP 的备用 API
- azure - 无法在 azure vm 中添加 ssh 密钥
- python - 使用特定键将字典作为参数传递的 Pythonic 方式
- java - 减少线条的粗细