とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

Visual C++ 2012はメンバ関数のcv修飾でバグがある

Visual Studio 2012(Visual C++ 11.0)はメンバ関数のcv修飾にバグがある。

再現コード

以下のコードをコンパイルするとコンパイルエラーになる。

template<class T> struct s{};

typedef int f() const;
s<f>           ok;  // OK
s<int() const> bug; // Compile error, why?

int main(){}
error C2270: 'abstract declarator' : メンバーでない関数が、メモリ モデル修飾子を伴って宣言されています。

規格

規格を見るとN3337(PDF) 8.3.5/6に次のように書かれている。

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).
The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top
of the function type. In the latter case, the cv-qualifiers are ignored. [ Note: a function type that has a
cv-qualifier-seq is not a cv-qualified type; there are no cv-qualified function types. —end note ] [ Example:
typedef void F();
struct S {
const F f; // OK: equivalent to: void f();
};
—end example ] The return type, the parameter-type-list, the ref-qualifier, and the cv-qualifier-seq, but not
the default arguments (8.3.6) or the exception specification (15.4), are part of the function type. [ Note:
Function types are checked during the assignments and initializations of pointers to functions, references to
functions, and pointers to member functions. —end note ]

長いがポイントは次の一文。

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

s<int() const>int() constはtype-idに該当するのでコンパイルできるのが正しい。

他の処理系

GCC 4.3.6でエラー、Clang 3.0で警告になる。それ以降のバージョンでは正しくコンパイルできる。

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ