Error C1001 on Visual Studio 2015 with std::enable

I have some C++11 code that fails to compile on Visual Studio 2015 (Update 2), but compiles without error on both Clang and GCC. Therefore, I am suspecting a compiler bug in Visual Studio, but maybe my code is somehow ill-formed.

My real class BaseUnit is a template wrapper class over a double value, taking care about the physical dimensions of quantities (expressed as SI units m, kg, s, K). For example, the multiplication of a Speed with a Time template instance automatically gives a Distance instance. The problem occurs with the current implementation of the multiplication with a scalar. I have simplified the class as much as I could to show the problem.

#include <type_traits>

template<int M>
class BaseUnit
{
public:
    constexpr explicit BaseUnit(double aValue) : value(aValue) {}
    template<typename U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0>
        BaseUnit operator*(U scalar) const { return BaseUnit(value * scalar); }
    template<typename U, typename std::enable_if<std::is_arithmetic<U>::value, int>::type = 0>
        friend BaseUnit operator* (U scalar, BaseUnit v) { return BaseUnit(scalar*v.value); }
protected:
    double value;
};

int main()
{
    BaseUnit<1> a(100);
    a = 10 * a;  // <-- error C1001 here
    return 0;
}

When compiling on Visual Studio, whatever the command line options, an internal error C1001 appears:

C:temp>cl bug.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23918 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

bug.cpp
bug.cpp(19): fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'msc1.cpp', line 1433)
 To work around this problem, try simplifying or changing the program near the locations listed above.
Please choose the Technical Support command on the Visual C++
 Help menu, or open the Technical Support help file for more information
Internal Compiler Error in C:Program Files (x86)Microsoft Visual Studio 14.0VCBINcl.exe.  You will be prompted to send an error report to Microsoft later.
INTERNAL COMPILER ERROR in 'C:Program Files (x86)Microsoft Visual Studio 14.0VCBINcl.exe'
    Please choose the Technical Support command on the Visual C++
    Help menu, or open the Technical Support help file for more information

From some experiments, it happens that both operator* definitions are needed for the error to appear. If either the prefix or the postfix version is removed, the sample code can compile fine.

I may fill out a bug report on Microsoft if this behavior is confirmed to be a bug, and not already a well-known issue of the compiler.


According to the current draft of C++ standard:

14.1 Template parameters [temp.param]
1 The syntax for template-parameters is:
template-parameter:
   type-parameter
   parameter-declaration
type-parameter:
  type-parameter-key ...opt identifieropt
  type-parameter-key identifieropt= type-id
  template < template-parameter-list > type-parameter-key ...opt identifieropt
  template < template-parameter-list > type-parameter-key identifieropt= id-expression
type-parameter-key:
   class
   typename

As the result you have syntax error (you can report MS about that the compiler does not detect such error). So in your case correct well-formed code is:

template<int M>
class BaseUnit
{
public:
  constexpr explicit BaseUnit(double aValue) : value(aValue) {}
  template<typename U, typename T = typename std::enable_if<std::is_arithmetic<U>::value, int>::type>
  BaseUnit<M> operator*(U scalar) const { return BaseUnit<M>(value * scalar); }
  template<typename U, typename T = typename std::enable_if<std::is_arithmetic<U>::value, int>::type>
  friend BaseUnit operator* (U scalar, BaseUnit v) { return BaseUnit(scalar*v.value); }
protected:
  double value;
};

int main()
{
  BaseUnit<1> a(100);
  a = 10 * a;  // ok
  a = "19" * a;  // error
  return 0;
}
链接地址: http://www.djcxy.com/p/92478.html

上一篇: Office365 REST API的API限制

下一篇: 使用std :: enable在Visual Studio 2015上错误C1001