description | title | ms.date | f1_keywords | helpviewer_keywords | ms.assetid |
---|---|---|---|---|---|
Learn more about: Compiler Error C2338 |
Compiler Error C2338 |
02/22/2022 |
C2338 |
C2338 |
49bba575-1de4-4963-86c6-ce3226a2ba51 |
Compiler Error C2338
Error message
Error C2338 can be caused by a static_assert
error during compilation. The message is supplied by the static_assert
parameters.
Error C2338 can also be generated by external providers to the compiler. In most cases, these errors are reported by an attribute provider DLL, such as ATLPROV. Some common forms of this message include:
-
‘attribute‘ Atl Attribute Provider : error ATLnumber message
-
Incorrect usage of attribute ‘attribute‘
-
‘usage‘: incorrect format for attribute ‘usage’
These errors are often unrecoverable, and may be followed by a fatal compiler error.
To fix these issues, correct the attribute usage. For example, in some cases, attribute parameters must be declared before they can be used. If an ATL error number is provided, check the documentation for that error for more specific information.
In Standard C++11 and later, constexpr
functions are no longer considered noexcept
by default when used in a constant expression. This behavior change comes from the resolution of Core Working Group (CWG) CWG 1351 and is enabled in /permissive-
mode. The following example compiles in Visual Studio 2019 version 16.1 and earlier, but produces C2338 in Visual Studio 2019 version 16.2:
// c2338.cpp // Compile using: cl /EHsc /W4 /permissive- c2338.cpp constexpr int f() { return 0; } int main() { static_assert(noexcept(f()), "f should be noexcept"); // C2338 in 16.2 }
To fix the error, add the noexcept
expression to the function declaration:
// c2338_fixed.cpp // Compile using: cl /EHsc /W4 /permissive- c2338_fixed.cpp constexpr int f() noexcept { return 0; } int main() { static_assert(noexcept(f()), "f should be noexcept"); }
I am receiving the following error when I attempt to compile a unit test in Visual Studio 2013:
Error 1 error C2338: Test writer must define specialization of ToString<Q* q> for your class class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > __cdecl Microsoft::VisualStudio::CppUnitTestFramework::ToString<struct HINSTANCE__>(struct HINSTANCE__ *).
You can replicate the error by having a test method such as below:
const std::wstring moduleName = L"kernel32.dll";
const HMODULE expected = GetModuleHandle(moduleName.c_str());
Microsoft::VisualStudio::CppUnitTestFramework::Assert::AreEqual(expected, expected);
Does anyone know how I need to go about writing such a specialization of ToString
?
asked Feb 26, 2015 at 10:24
Class SkeletonClass Skeleton
2,9036 gold badges31 silver badges51 bronze badges
I had the same problem when comparing class objects.
For me I could resolve it by simply writing
Assert::IsTrue(bitmap1 == bitmap2);
instead of
Assert::AreEqual(bitmap1, bitmap2);
answered Jan 17, 2017 at 7:59
Matthias BäßlerMatthias Bäßler
4801 gold badge5 silver badges11 bronze badges
I managed to resolve the issue by adding the following code into my unit test class file:
/* ToString specialisation */
namespace Microsoft
{
namespace VisualStudio
{
namespace CppUnitTestFramework
{
template<> static std::wstring ToString<struct HINSTANCE__>
(struct HINSTANCE__ * t)
{
RETURN_WIDE_STRING(t);
}
}
}
}
I based this on the contents of CppUnitTestAssert.h (which is where the compilation error occurs — double clicking on the compilation error will open this file for you).
Near the top of the file (and only a few lines down if you double clicked on the compilation error as noted above) you can see a set of ToString
templates. I copied one of these lines and pasted it into my test class file (enclosed in the same namespaces as the original templates).
I then simply modified the template to match the compilation error (specifically <struct HINSTANCE__>(struct HINSTANCE__ * t)
).
For my scenario, using RETURN_WIDE_STRING(t)
is sufficient in displaying a mismatch in my AreSame
assertion. Depending on the type used you could go further and pull out some other meaningful text.
answered Feb 26, 2015 at 13:06
Class SkeletonClass Skeleton
2,9036 gold badges31 silver badges51 bronze badges
1
As of 2021, the answer Class Skeleton provided did not work for me, but I made some modifications based on it and the following compiled. Basically the lines that follows the error message provided some examples.
template<>
inline std::wstring __cdecl Microsoft::VisualStudio::CppUnitTestFramework::ToString<MyClass>(const MyClass& t)
{
// replace with your own, here is just my example
// RETURN_WIDE_STRING(t.ToString().c_str());
}
Replace MyClass
with your class.
answered Jul 2, 2021 at 16:47
Message Text
text
Circumstances (External)
This error serves mainly as a placeholder for errors generated externally to
the compiler. The message text is entirely in the hands of the external component,
which is why it is shown simply as text above.
For this mechanism to be useful, the text would
describe the error in some detail, perhaps even with its own scheme of error numbers.
The external component will be an attribute provider DLL, such as ATLPROV. Indeed,
since Microsoft does not document how to write attribute providers, ATLPROV is in
practice the only cause of externally generated C2338 errors.
ATL Errors
All ATL errors generated by ATLPROV feed back to the compiler as C2338. The complete
error message is:
position : error C2338: attribute Atl Attribute Provider : error ATLnumber: message
where position (the file name and line number)
is generated by the compiler, as usual, but everything from
attribute onwards is from ATLPROV, including most
notably the ATL error number and message text.
Circumstances (Internal)
Three cases exist in which the compiler may itself raise error C2338, with the
compiler’s own message text.
Boxing by Dynamic Cast
The history is not known, but it seems that the cloning of a value type into
a managed object may once upon a time have been done by casting, perhaps before
(and prompting) invention of the __box keyword. In
this case of an internally generated C2338, the message text is
deprecated use of dynamic_cast: use __box instead to box a value type
To see this admittedly obscure (and certainly undocumented) error, compile the
following with the /clr option:
#using <mscorlib.dll> using namespace System; Object *box (int x) { return dynamic_cast <Object *> (x); // C2338 }
Bad Input to the Attribute Provider Provider
The other cases of internally generated C2338 both arise from misuse of the attribute
provider provider (ProvProv). This special attribute provider is implemented within
the compiler to help other attribute providers define their own attributes, most
notably to standardise the grammar.
Bad Group Attribute
Error C2338 occurs with the message text
'group': incorrect format for attribute 'group'
when the group given as the value of the
group attribute is not one of:
eComGroup, eCompilerGroup,
eComPlusMetaDataGroup, eControlGroup,
eCPlusPlusGroup, eDBConsumerGroup,
eDBProviderGroup, eDebugGroup,
eDHTMLGroup, eHPS,
eIDLGroup, eInterfaceGroup,
eModuleGroup, eRegistryGroup,
eStockPMEGroup, eUserDefinedGroup
or eWindowGroup
Because this validation is performed as part of ProvProv’s parsing of the group
attribute, this case of error C2338 does not require real-world use of the ProvProv
attributes, just that they be activated and that the group
attribute be given with an invalid value. Even the following suffices:
[ provider ("ProvProv", "6462678A-83F5-11D2-B8DA-00C04F799BBB") ]; [ group = rubbish ]; // C2338 and (most likely) C1903
Bad Usage Attribute
Error C2338 occurs with the message text
'usage': incorrect format for attribute 'usage'
when the usage given as the value of the
usage attribute is not one of the following or a
bit-wise OR of more than one:
eAnonymousUsage, eAnyIDLUsage,
eAnyUsage, eAsynchronousUsage,
eClassUsage, eCoClassMemberUsage,
eCoClassMethodUsage, eCoClassUsage,
eCOMInterfaceUsage, eDefineTagUsage,
eEnumUsage, eEventUsage,
eGlobalDataUsage, eGlobalMethodUsage,
eIDLModuleUsage, eIllegalUsage,
eInterfaceUsage, eInterfaceMethodUsage,
eInterfaceParameterUsage, eLocalUsage,
eMemberUsage, eMethodParameterUsage,
eMethodUsage, eModuleUsage,
ePropertyUsage, eStructUsage,
eTemplateUsage, eTypedefUsage,
or eUnionUsage
However, this validation is not performed unless ProvProv injects code for the
GetAttributeList method of the
IAttributeGrammar interface. Such injection is attempted
only in response to the implement_grammar attribute
and requires source code that is at least suggestive of real-world use. For a roughly
minimal example, create empty header files named
- fake_p1.h
- quickhash.h
- usage.h
and compile
[ provider ("ProvProv", "6462678A-83F5-11D2-B8DA-00C04F799BBB"), ]; [ provider_name = {"test", "00000000-0000-0000-0000-000000000000"}, implement_grammar ] class Test { [ define_attribute = "rubbish", usage = rubbish ]; } // C2338 and (most likely) C1903
Coding Error
Note that in both the group and
usage cases, error C2338 is most likely followed
by fatal error C1903. This is no orderly exit.
It is instead the most likely outcome of a coding error in the compiler. The code
that asks for error C2338 assumes there will be no return, as if C2338 were fatal.
Since there is a return, the compiler soon executes whatever code happens to follow
in memory. The best and most likely outcome is a CPU fault, such as would ordinarily
be presented as an internal compiler error (C1001),
but is presented instead as C1903 because of the previous error. To let the CPU
exception escape the compiler for easy viewing, add the
/Bd option when compiling the examples.
Message Text
text
Circumstances (External)
This error serves mainly as a placeholder for errors generated externally to
the compiler. The message text is entirely in the hands of the external component,
which is why it is shown simply as text above.
For this mechanism to be useful, the text would
describe the error in some detail, perhaps even with its own scheme of error numbers.
The external component will be an attribute provider DLL, such as ATLPROV. Indeed,
since Microsoft does not document how to write attribute providers, ATLPROV is in
practice the only cause of externally generated C2338 errors.
ATL Errors
All ATL errors generated by ATLPROV feed back to the compiler as C2338. The complete
error message is:
position : error C2338: attribute Atl Attribute Provider : error ATLnumber: message
where position (the file name and line number)
is generated by the compiler, as usual, but everything from
attribute onwards is from ATLPROV, including most
notably the ATL error number and message text.
Circumstances (Internal)
Three cases exist in which the compiler may itself raise error C2338, with the
compiler’s own message text.
Boxing by Dynamic Cast
The history is not known, but it seems that the cloning of a value type into
a managed object may once upon a time have been done by casting, perhaps before
(and prompting) invention of the __box keyword. In
this case of an internally generated C2338, the message text is
deprecated use of dynamic_cast: use __box instead to box a value type
To see this admittedly obscure (and certainly undocumented) error, compile the
following with the /clr option:
#using <mscorlib.dll> using namespace System; Object *box (int x) { return dynamic_cast <Object *> (x); // C2338 }
Bad Input to the Attribute Provider Provider
The other cases of internally generated C2338 both arise from misuse of the attribute
provider provider (ProvProv). This special attribute provider is implemented within
the compiler to help other attribute providers define their own attributes, most
notably to standardise the grammar.
Bad Group Attribute
Error C2338 occurs with the message text
'group': incorrect format for attribute 'group'
when the group given as the value of the
group attribute is not one of:
eComGroup, eCompilerGroup,
eComPlusMetaDataGroup, eControlGroup,
eCPlusPlusGroup, eDBConsumerGroup,
eDBProviderGroup, eDebugGroup,
eDHTMLGroup, eHPS,
eIDLGroup, eInterfaceGroup,
eModuleGroup, eRegistryGroup,
eStockPMEGroup, eUserDefinedGroup
or eWindowGroup
Because this validation is performed as part of ProvProv’s parsing of the group
attribute, this case of error C2338 does not require real-world use of the ProvProv
attributes, just that they be activated and that the group
attribute be given with an invalid value. Even the following suffices:
[ provider ("ProvProv", "6462678A-83F5-11D2-B8DA-00C04F799BBB") ]; [ group = rubbish ]; // C2338 and (most likely) C1903
Bad Usage Attribute
Error C2338 occurs with the message text
'usage': incorrect format for attribute 'usage'
when the usage given as the value of the
usage attribute is not one of the following or a
bit-wise OR of more than one:
eAnonymousUsage, eAnyIDLUsage,
eAnyUsage, eAsynchronousUsage,
eClassUsage, eCoClassMemberUsage,
eCoClassMethodUsage, eCoClassUsage,
eCOMInterfaceUsage, eDefineTagUsage,
eEnumUsage, eEventUsage,
eGlobalDataUsage, eGlobalMethodUsage,
eIDLModuleUsage, eIllegalUsage,
eInterfaceUsage, eInterfaceMethodUsage,
eInterfaceParameterUsage, eLocalUsage,
eMemberUsage, eMethodParameterUsage,
eMethodUsage, eModuleUsage,
ePropertyUsage, eStructUsage,
eTemplateUsage, eTypedefUsage,
or eUnionUsage
However, this validation is not performed unless ProvProv injects code for the
GetAttributeList method of the
IAttributeGrammar interface. Such injection is attempted
only in response to the implement_grammar attribute
and requires source code that is at least suggestive of real-world use. For a roughly
minimal example, create empty header files named
- fake_p1.h
- quickhash.h
- usage.h
and compile
[ provider ("ProvProv", "6462678A-83F5-11D2-B8DA-00C04F799BBB"), ]; [ provider_name = {"test", "00000000-0000-0000-0000-000000000000"}, implement_grammar ] class Test { [ define_attribute = "rubbish", usage = rubbish ]; } // C2338 and (most likely) C1903
Coding Error
Note that in both the group and
usage cases, error C2338 is most likely followed
by fatal error C1903. This is no orderly exit.
It is instead the most likely outcome of a coding error in the compiler. The code
that asks for error C2338 assumes there will be no return, as if C2338 were fatal.
Since there is a return, the compiler soon executes whatever code happens to follow
in memory. The best and most likely outcome is a CPU fault, such as would ordinarily
be presented as an internal compiler error (C1001),
but is presented instead as C1903 because of the previous error. To let the CPU
exception escape the compiler for easy viewing, add the
/Bd option when compiling the examples.
Недавно скомпилирован с Visual Studio 2017Brofiler(Профилировщик C ++), я столкнулся с некоторыми проблемами, одна из которыхError C2338。
причина
Поскольку он используется в шаблоне контейнера STLconst
В стандарте C ++ 11 это запрещено! Старая версия Visual Studio не такая строгая, поэтому ее вообще можно скомпилировать. Вот, кстати, перечислите требования к параметрам шаблона в последнем стандарте, и постарайтесь обратить на это внимание при написании кода в будущем.
Standard | Requirement for T |
---|---|
C++03 | any type |
C++11 | any non-const, non-reference object type |
C++14 | any non-const object type |
C++17 | any cv-unqualified object type |
решить
Из-за специфики шаблонов C ++ сообщения об ошибках общих шаблонов очень «загадочные». На моем компьютере сообщение об ошибке относится к файлу xmemory0, но дело не в том, что этот файл неправильный, а потому, что в шаблоне контейнера STL используется наш собственный код.const
Вызвал ошибку.
Вы можете искать по тексту «<const
«, вы можете в основном найти большинство проектов, используемых в шаблонеconst
Код, которыйconst
Просто удали его. Если вы не можете найти все, попробуйте:< const
、const>
、const >
И так далее, или найдите это с помощью регулярных выражений.
Например, в исходном коде Brofiler 1.1.2 он используется в двух местахconst
. Обратите внимание, что определение контейнера удаленоconst
Позже это обычно вызывает ошибки в коде, используемом некоторыми контейнерами. Мы можем использоватьconst_cast
Приходите удалить ограничение const в коде следующим образом:
// Файл: Core.h
// FIX Error C2338
//typedef MemoryPool<const EventData*, 32> CategoryBuffer;
typedef MemoryPool<EventData*, 32> CategoryBuffer;
BRO_INLINE void RegisterCategory(const EventData& eventData)
{
// FIX Error C2338
//categoryBuffer.Add() = &eventData;
categoryBuffer.Add() = const_cast<EventData*>(&eventData);
}
// Файл: Sampler.cpp
OutputDataStream& Sampler::Serialize(OutputDataStream& stream)
{
// ...
// FIX Error C2338
//std::vector<const Symbol * const> symbols;
std::vector<Symbol*> symbols;
for each (DWORD64 address in addresses)
if (auto symbol = symEngine.GetSymbol(address))
//symbols.push_back(symbol);
symbols.push_back(const_cast<Symbol*>(symbol));
// ...
}
- Remove From My Forums
-
Question
-
Hi,
I have a regression with the new v110 toolset. The following code compiles correctly using Visual C++ 2010, but not using Visual C++ 2012:
#include "stdafx.h" #include <atlplus.h> #include <atldbcli.h> [db_source(L"Provider=SQLOLEDB.1;Persist Security Info=False;User ID=user;Password=password;Initial Catalog=database;Data Source=localhost;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=host;Use Encryption for Data=False;Tag with column collation when possible=False")] class abc { public: HRESULT del(LONG id) { HRESULT hr; [db_command(source_name = "m_Connection", hresult = "hr", command=_T(" DELETE FROM abc WHERE ID = ?([in] id) "))]; return hr; } protected: CDataConnection m_Connection; }; int _tmain(int argc, _TCHAR* argv[]) { return 0; }
The output log is as follows, only when compiling with the new v110 toolset (compiles OK with the Visual C++ 2010 toolset):
1>------ Début de la régénération globale : Projet : db_command_error, Configuration : Debug Win32 ------ 1>La génération a démarré 2013-06-14 10:21:58. 1>_PrepareForClean: 1> Suppression du fichier "Debugdb_command_error.lastbuildstate". 1>InitializeBuildStatus: 1> Création de "Debugdb_command_error.unsuccessfulbuild", car "AlwaysCreate" a été spécifié. 1>ClCompile: 1> stdafx.cpp 1> db_command_error.cpp 1>d:testdb_command_errordb_command_errordb_command_error.cpp(14): error C2338: db_command 1>Atl Attribute Provider : error ATL2010: Identificateur non déclaré "id)". 1>d:testdb_command_errordb_command_errordb_command_error.cpp(14): error C2059: erreur de syntaxe : ')' 1> L'erreur suivante s'est produite dans le texte injecté : 1> 1> CCommand<CColumnAccessor, CNoRowset> _cmd; 1> 1> 1> *d:testdb_command_errordb_command_errordebugdb_command_error.inj:2(18) : error C2059: erreur de syntaxe : ')' 1> L'erreur suivante s'est produite dans le texte injecté : 1> 1> _cmd.SetParameterBuffer((BYTE*)&id)); 1> 1> 1> 1>ÉCHEC de la build. 1> 1>Temps écoulé 00:00:03.27 ========== Régénération globale : 0 a réussi, 1 a échoué, 0 a été ignoré ==========
Roughly, it seems that the ATL attribute processor takes an extra character (here a closing parenthesis) as part of the identifier.
Is there a known workaround ?
-
Edited by
Friday, June 14, 2013 6:09 PM
-
Edited by
Answers
-
-
Edited by
Arnaud Faucher
Monday, June 17, 2013 1:01 PM -
Marked as answer by
Elegentin Xie
Tuesday, June 18, 2013 5:38 AM
-
Edited by