2

The following code gives C2660 error in Visual Studio 2015 Community:

class Logger {
public:
    template <class T> void writeLine(const T& value) {
        if (this->filestream.is_open()) {
            filestream << object << std::endl;
        }
    }

    template <typename T> void write(const T& value) {
        if (this->filestream.is_open()) {
            filestream << value;
        }
    }

    template <typename T, typename... Targs> void write(const T& value, const Targs&... args) {
        if (this->filestream.is_open()) {
            filestream << value;
            this->write(args...);
        }
    }

    // ... singleton stuff
}

I'm calling the function like this:

#define LOG(x) Logger::instance().write(__FILE__, " (line ", __LINE__, "): ", x, std::endl);

Here is the error in the output log:

encoder.cpp(51): error C2660: 'Logger::write': function does not take 6 arguments
Ali Alidoust
  • 93
  • 3
  • 5

2 Answers2

2

The problem is that std::endl is itself a template

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );

Therefore a possible solution could be

var.write(__FILE__, " (line ", __LINE__, "): ", 22, std::endl<char, std::char_traits<char>>);

More information on this issue here

Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246
1

std::endl is a template, and the compiler doesn't have enough information to select an appropriate specialization. There are a multitude of ways to side step this:

  • use std::endl<char,std::char_traits<char>> for your final argument (yuck).
  • use '\n', which obviously isn't equivalent, but will probably work.
  • create a specialized Logger::endl and send that.

A decent example of the latter of these can be found here.


Unrelated, you should probably consider using perfect forwarding regardless. It should be trivial to adapt your template members to do so.

template <typename T>
void write(T&& value) {
    if (this->filestream.is_open()) {
        filestream << std::forward<T>(value);
    }
}

template <typename T, typename... Args>
void write(T&& value, Args&&... args)
{
    this->write(std::forward<T>(value));
    this->write(std::forward<Args>(args)...);
}

See here: Advantages of using forward, and the linked article, The Forwarding Problem.

Community
  • 1
  • 1
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • I would have never guessed that the `std::endl` is making the problem. I used the first solution and it works perfectly. Why is perfect forwarding code better to use? – Ali Alidoust Nov 18 '16 at 11:30
  • @AliAlidoust There are plenty of good references on the forwarding problem, and how perfect forwarding addresses it. See here: [Advantages of using `forward`](http://stackoverflow.com/questions/3582001/advantages-of-using-forward), and the linked article, [The Forwarding Problem](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm). They'll explain it far better than I could. – WhozCraig Nov 18 '16 at 11:33