werner
werner

Reputation: 11

Compilation error C2976 with boost::asio by using template with std::enable_if

I've written a c++ class that work's fine by using it in a test program. By using it in my project, there is a compilation error C2976. So i reduced the code to show the problem:

source.h

#include <type_traits>
//#include <boost/asio.hpp>

namespace myNS {

class Dummy {
public:
   Dummy() {}
   ~Dummy() {}

   template<class T> struct _isValidType : std::false_type {};
   template<> struct _isValidType<bool> : std::true_type {};
   template<> struct _isValidType<int> : std::true_type {};
   template<class T> struct isValidType : _isValidType<std::remove_cv_t<T>>::type {};

   template<typename OUT, typename std::enable_if<isValidType<OUT>::value>::type* dummy = nullptr>
   OUT doSomething() {  OUT out{}; return out; }
};

} /* namespace myNS */

source.cpp

#include "source.h"

int main() {
   myNS::Dummy d;
   bool b = d.doSomething<bool>();
}

There is no compilation error when boost::asio is not included. By including boost::asio the compiler runs in error on the last template definition:

source.h(14): error C2976: "Dummy::isValidType": Nicht genügend Vorlage-Argumente.
source.h(12): note: Siehe Deklaration von "Dummy::isValidType"
source.h(14): error C2955: "Dummy::isValidType" : Für die Verwendung von Klasse Vorlage ist eine Vorlage-Argumentliste erforderlich
source.h(12): note: Siehe Deklaration von "Dummy::isValidType"
source.h(15): error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.

Does anyone know this problem? Is it the fault of boost::asio, of MSVC, or is it my fault? In this example boost::asio is not necessary to be included, but in my project i have to include it.
I'm working with MS Visual Studio Community 2017 V 15.5.5 and use the boost library v1.66.0.

Thanks!

Upvotes: 0

Views: 314

Answers (1)

Mihayl
Mihayl

Reputation: 3911

This caused by some bad #define OUT ... (see Live Repro).

Rename your OUT type parameter to something else and move the explicit specializations outside the class.

class Dummy {
public:
    // ...
    template<typename T, typename std::enable_if<isValidType<T>::value>::type* dummy = nullptr>
    T doSomething() {  T out{}; return out; }
}:

template<> struct Dummy::_isValidType<bool> : std::true_type {};
template<> struct Dummy::_isValidType<int> : std::true_type {};

Upvotes: 1

Related Questions