I have an issue where the following code compiles on GCC (4.8+ tested) and Clang (3.4+ tested) but does not compile on Visual Studio 2015 (VC++ 14.0).
Foo.h:
#include <functional>
namespace Error {
enum class Code;
static const Code None = static_cast<Code>(0);
}
class Foo{
public:
std::function<Error::Code()> Run();
};
Foo.cpp
#include "Foo.h"
#include <iostream>
std::function<Error::Code()> Foo::Run() {
return [&]() {
std::cout << "hello\n";
return Error::None;
};
}
main.cpp:
#include "Foo.h"
namespace Error {
enum class Code {
None = 0,
Error = 1,
};
}
int main() {
Foo foo;
foo.Run()();
}
The resulting error in VC++ 14.0 is as follows:
Foo.obj : error LNK2001: unresolved external symbol "enum Error::Code __cdecl std::_Invoke_ret<enum Error::Code,class <lambda_813e82254384ef384f6a5fe34e885f01> &>(struct std::_Forced<enum Error::Code,0>,class <lambda_813e82254384ef384f6a5fe34e885f01> &)" (??$_Invoke_ret@W4Code@Error@@AAV<lambda_813e82254384ef384f6a5fe34e885f01>@@@std@@YA?AW4Code@Error@@U?$_Forced@W4Code@Error@@$0A@@0@AAV<lambda_813e82254384ef384f6a5fe34e885f01>@@@Z)
Which I believe is an internal std library function for implementng std::function
.
This code is similar to usage of an internal library I'm trying to use that shares a standard program interface for tools, but forward declares Error Codes so they can be customized. I believe this should be valid code based on §7.2 (see this answer) The enum, though forward declared, should be a complete type and usable as a return value. Here is the relevant bit in the standard:
An opaque-enum-declaration is either a redeclaration of an enumeration in the current scope or a declaration of a new enumeration. [Note: An enumeration declared by an opaque-enum-declaration has fixed underlying type and is a complete type. The list of enumerators can be provided in a later redeclaration with an enum-specifier. —end note ]
Is this code valid? If so, is there a work around to get VC++ to accept it?