【问题标题】:Error on successive enable_if overload call连续 enable_if 重载调用出错
【发布时间】:2021-03-22 17:55:26
【问题描述】:

基本上,这个想法是为任何可迭代的东西重载operator <<,例如正确定义 begin() 和迭代器方案的向量、列表和自定义类。

最初,我编写了以下原型

template<template<class, class ...> class Container, class T, class ... Whatever>
std::ostream& operator<<(std::ostream& out, const Container<T, Whatever...>& container) { stuff }

问题是我显然会与模板定义匹配的任何内容发生冲突并且已经重载&lt;&lt;,例如std::string。所以,如果我写cout &lt;&lt; string { "Hello" },它是模棱两可的。我明白为什么。

因此,当且仅当尚未定义 operatorstd::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&lt;class Container&gt; std::ostream&amp; operator&lt;&lt;(std::ostrea&amp; out, const Container&amp; 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 是包含上述代码的文件。

【问题讨论】:

  • 请提供错误信息。
  • error: no match for ‘operator&lt;&lt;’ (operand types are ‘std::ostream {aka std::basic_ostream&lt;char&gt;}’ and ‘std::vector&lt;int&gt;’) cout &lt;&lt; v2 &lt;&lt; endl;
  • 我还编辑了我的原始帖子以添加完整的代码示例以复制/粘贴
  • 仍然无法复制godbolt.org/z/83h9Gh。你用什么编译器?哪个版本?哪些编译标志?顺便说一句,它停止为 GCC 8.1 及更低版本工作。但错误也适用于v1,而不仅仅是v2
  • g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 。我用g++ -std=c++17 -o sample sample.cpp编译

标签: c++ operator-overloading c++17 sfinae enable-if


【解决方案1】:

好吧,基本上,我的编译器版本太旧了。在 gcc 9.3 上,它按预期工作。

主题已关闭。 (我读到如果我没有足够的代表,我无法关闭自己的话题,而我没有......)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多