Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MSVC: modifiers not allowed on non-memberfunction

Tags:

c++

c++11

I wrote a Signal/Slot library (Codeproject article here), under linux, compiling with both Clang 3.5 and GCC4.9. It compiles without warnings on both compilers (also on versions 3.4 resp 4.8). When I got it all working, and posted the article online, it wasn't long until I got complaints that it's not working on MSVC. (Visual Studio Express 2013? I'm sorry, I'm not familiar with the versioning system.) I installed it in a VM to have a look for myself and found that it won't compile the following:

template <typename Signature>
struct RemoveCV;

template <typename R, typename ... Args>
struct RemoveCV<T, R (Args...)>
{
    using Type = R(Args...);
};

template <typename R, typename ... Args>
struct RemoveCV<T, R(Args...) const>
{
    using Type = R(Args...);
};

// more specializations for volatile and const volatile

// Usage:
template <typename Signature_>
struct Function
{
    using Signature = RemoveCV<Signature_>::Type;
};

// both Function<void()> and Function<void() const> now have 
// the same Signature: void()

The reason being that R(Args ...) is not a member function, so it can't have a const qualifier.

While it is of course true that it doesn't make sense to have a const qualifier on a non-memberfunction, I believe I read somewhere (here on SO, including a quote from the standard), that it is allowed as long as it's not bound to an actual function. I.e. it is allowed as a stand-alone type. Unfortunately I don't seem to be able to find that thread anymore...

I was just wondering who's right on this occasion: MSVC or GCC + Clang, and what the standard has to say about a standalone function signature like void() const.

like image 977
JorenHeit Avatar asked Jan 22 '15 10:01

JorenHeit


1 Answers

Well, I believe that it appears that you (and GCC and Clang) are right, with regards to what the standard says. From §8.3.5/6 (in N3376), (emphasis mine):

A cv-qualifier-seq or a ref-qualifier shall only be part of:

— the function type for a non-static member function,

— the function type to which a pointer to member refers,

— the top-level function type of a function typedef declaration or alias-declaration,

— the type-id in the default argument of a type-parameter (14.1), or

the type-id of a template-argument for a type-parameter (14.2).

like image 80
JBL Avatar answered Oct 23 '22 14:10

JBL