最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Visual Studio error C2953 when redefining operator << with template parameter packs - Stack Overflow

programmeradmin2浏览0评论

All,

I ran into a C++20 Visual Studio error C2593 ("Operator << is ambiguous") when compiling this simple program patterned from section 4.2 of the Vandevoorde, Josuttis and Gregor book "C++ Templates - The Complete Guide":

#include <iostream>

std::ostream& operator << (std::ostream& str, int s)
{
    return str << s << ' ';
}

template <typename T>
void print(Args... args)
{
    (std::cout << ... << args) << std::endl;
}

int main 
{
  print(1,2,3,4) 
  return 0;
}

I want the output to be "1 2 3 4", hence the operator redefinition to add a space after each displayed value. The C2593 error happens at this line,

return str << s << ' ';

but if I comment out that line, I get the same error at the fold expression line

(std::cout << ... << args) << std::endl;

I'm just learning C++ templates, so, can anyone spot what I'm doing wrong ? Thanks!

All,

I ran into a C++20 Visual Studio error C2593 ("Operator << is ambiguous") when compiling this simple program patterned from section 4.2 of the Vandevoorde, Josuttis and Gregor book "C++ Templates - The Complete Guide":

#include <iostream>

std::ostream& operator << (std::ostream& str, int s)
{
    return str << s << ' ';
}

template <typename T>
void print(Args... args)
{
    (std::cout << ... << args) << std::endl;
}

int main 
{
  print(1,2,3,4) 
  return 0;
}

I want the output to be "1 2 3 4", hence the operator redefinition to add a space after each displayed value. The C2593 error happens at this line,

return str << s << ' ';

but if I comment out that line, I get the same error at the fold expression line

(std::cout << ... << args) << std::endl;

I'm just learning C++ templates, so, can anyone spot what I'm doing wrong ? Thanks!

Share asked Mar 8 at 22:44 AlbertusAlbertus 666 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

Your code has a few problems. Each is pretty minor individually, but they're still enough to keep it from working.

First of all, there's an existing overload of operator<< to insert an int into an ostream, so you don't need to write that yourself (and attempting to do so as you've done creates an ambiguous overload, so the code won't compile). One way to write out the space after each item is to convert each to a string, and add the space to the end of the string.

Second, you haven't defined print as a variadic template, even though you've tried to use it as one.

Third, you need an empty pair of parens after main to get a function definition.

Fixing those gives us something like this:

#include <iostream>
#include <string>

template <typename ...Args>
void print(Args... args)
{
    (std::cout << ... << (std::to_string(args) + ' ')) << std::endl;
}

int main() 
{
  print(1,2,3,4);
}

And this works.

live on Godbolt

As a rather minor aside, I'd personally write a new-line ('\n') to the stream rather than using std::endl. In this case it's not a big deal, but std::endl flushes the output stream, which is rarely desired, but can cause a pretty serious slow-down if done frequently.

Thanks, all, @TedLyngmo told me what I did wrong. I cannot overload operator << for standard types, so, I needed to create a class and use it instead to unpack my template parameters. Here's a sample code that works, again, patterned from that Vandervoode, Josuttis and Gregor book:

#include <iostream>
#include <string>

template<typename T>
class AddSpace
{
private:
    T const& ref;
public:
    AddSpace(T const& r) : ref(r) {}
    friend std::ostream& operator << (std::ostream& str, AddSpace<T> s)
    {
        return str << s.ref << ' ';
    }
};

template <typename... Args>
void print(Args... args)
{
    // Fold expression unpacks args, creates one AddSpace object per arg, and outputs each AddSpace::ref to std::cout.
    (std::cout << ... << AddSpace(args)) << std::endl;
}

int main()
{
   
    print(1, 2, 3, 4);
    return 0;
}

Creating a user class, overloading operator << to take values from that class, and using it to unpack the template parameters, apparently does the job. It's a bit complicated but it works. So, again, thanks to you all!

发布评论

评论列表(0)

  1. 暂无评论