Меню

Visual studio c ошибка c2338

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 Skeleton's user avatar

Class SkeletonClass Skeleton

2,8136 gold badges30 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äßler's user avatar

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 Skeleton's user avatar

Class SkeletonClass Skeleton

2,8136 gold badges30 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

Paul Chen's user avatar

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");
}

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.

RRS feed

  • Remove From My Forums
  • Question

    • Moved by
      Jack Zhai-MSFTMicrosoft contingent staff
      Friday, April 18, 2014 6:45 AM
      Move to a more appropriate forum.

All replies

  • According to documentation, you can try defining a special symbol —
    _ATL_ALLOW_CHAR_UNSIGNED
    — however the workaround is not recommended and may not always work.

    Maybe you can consider other solutions for your problems and avoid the /J option.

  • Yes I saw that kludge but why after all these years does MS f me over. These are older projects (big) and not easily able to change and recheck for this situation.

    I hope someone can help with a «real» solution.

    Thanks again

  • Hi GSP_T,

    I am moving your thread into the
    Visual C++ Forum for dedicated support. Thanks for your understanding.

    Best Regard,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.

    Click
    HERE to participate the survey.

  • Hi,

    Is it a VS2010 project? What is the version of VS you build the project now?

    I found a KB about this similar error that you can have a reference.

    Error message when you compile a Visual C++ 2010 project that includes the Atlcomcli.h file

    http://support.microsoft.com/kb/982517

    You have a Microsoft Visual C++ 2010 project that includes the Atlcomcli.h file.

    • You specify the /J compiler option to define the _CHAR_UNSIGNED macro in the project.
    • You compile the project.

      To work around this problem, follow these pragma directives to include the Atlcomcli.h file:

      #pragma push_macro("ATLSTATIC_ASSERT")#undef ATLSTATIC_ASSERT
      #define ATLSTATIC_ASSERT(x,y)#include <atlcomcli.h>#undef ATLSTATIC_ASSERT#pragma pop_macro("ATLSTATIC_ASSERT")

    • Best regards,
    • Sunny
  • Yes this has been a 2010 project(s) for a very long time and never had the problem.

    I had to rebuild two systems, one Win7 the other 8.1, install 2010 Ultimate, SP1 and now when I build

    I get the error. Also my code does not specifily include the atlcomcli.h but some other file may pull that in. What bothers me is I never had to deal with this and now I do and to go back through 1000s of lines of code to make sure elevating a char does
    not extend the sign would be a big job.

    I just may do what you suggest.

    Thanks

  • Hi,

    Has your problem been solved? Or anything else I can provide?

    Best regards,

    Sunny

  • Was going to try the #pragma test but have not gotten around to it yet. If thats the official MS answer I guess it will have to do.

  • Where can I download this hotfix?  I tried to #pragma stuff but still got the same errors.

Решите проблему «Ошибка C2338. Стандарт C ++ запрещает контейнеры константных элементов, потому что распределитель»

Недавно скомпилирован с 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Просто удали его. Если вы не можете найти все, попробуйте:< constconst>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));

	// ...
}

ошибка C2338: Писатель теста должен определить специализацию ToString <const q& q> для вашего класса

Вопрос:

В настоящее время я получаю следующую ошибку для Visual Studio 2013 C++/CLI Native Unit Test.

error C2338: Test writer must define specialization of ToString<const 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<class LTI::IPCommon::CPPBoxesBuffer>(const class LTI::IPCommon::CPPBoxesBuffer &).  c:program files (x86)microsoft visual studio 12.0vcunittestincludecppunittestassert.h

Я пробовал решение, предложенное в VS2012: Ошибка с модульным тестом: Assert :: AreEqual (объект, объект) не работал и написал специализацию, но это не сработало.

Вот класс в BoxesBuffer.h:

    class CPPBoxesBuffer{
private:
unsigned char* _data;
int _lines;

public:
CPPBoxesBuffer(unsigned char* data, int lines){ _data = data; _lines = lines; };

// Methods for std::map. Class must be Assignable
CPPBoxesBuffer(){ _data = nullptr; _lines = 0; };

CPPBoxesBuffer(const CPPBoxesBuffer& other)
{
_lines = other._lines;
_data = other._data;
}

CPPBoxesBuffer& operator=(const CPPBoxesBuffer& other)
{
_lines = other._lines;
_data = other._data;
return *this;
}

bool operator==(const CPPBoxesBuffer& other) const
{
return _lines == other._lines && _data == other._data;
}


};

Вот тест:

    TEST_METHOD(ShouldSetAndGetCppBoxesBufferData)
{
std::string key = "WhenPassingData";
unsigned char t[5] = { 'a', 'b', 'c', 'd', 'e' };
CPPBoxesBuffer data(t, 5);
auto result = data;
auto db = data == result; // This compiles.

Assert::AreEqual(data, result);  // This fails with the error.
}

Вот специализация, которую я написал:

#include "CppUnitTest.h"
#include "BoxesBuffer.h"

namespace Microsoft
{
namespace VisualStudio
{
namespace CppUnitTestFramework
{
template<> static std::wstring ToString<CPPBoxesBuffer>(const class CPPBoxesBuffer& t) { return L"CppBoxesBuffer"; }
}
}
}

Что я делаю не так?

Лучший ответ:

Ваша специализация объявлена где-то, что строка Assert::AreEqual может ее увидеть? Я считаю, что если он в другом файле cpp и не прототипирован в заголовок, он не будет найден, если скомпилирован Assert::AreEqual.

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Visual studio 2012 kernelbase dll ошибка c06d007e
  • Visual studio 2008 redistributable files возвратило ошибку vipnet