Ali Alidoust
Ali Alidoust

Reputation: 93

Calling a variadic template function gives error C2660 in Visual Studio 2015

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

Upvotes: 2

Views: 388

Answers (2)

WhozCraig
WhozCraig

Reputation: 66194

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.

Upvotes: 1

Marco A.
Marco A.

Reputation: 43662

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

Upvotes: 2

Related Questions