Error c2440 function style cast

C++ Documentation. Contribute to MicrosoftDocs/cpp-docs development by creating an account on GitHub.
description title ms.date f1_keywords helpviewer_keywords no-loc ms.assetid

Learn about type conversion errors that cause Compiler Error C2440.

Compiler Error C2440

08/27/2021

C2440

C2440

struct

const

36e6676c-f04f-4715-8ba1-f096c4bf3b44

Compiler Error C2440

initializing‘ : cannot convert from ‘type1‘ to ‘type2
conversion‘ : cannot convert from ‘type1‘ to ‘type2

The compiler can’t implicitly convert from *type1* to *type2*, or can’t use the specified cast or conversion operator.

Remarks

The compiler generates C2440 when it can’t convert from one type to another, either implicitly or by using the specified cast or conversion operator. There are many ways to generate this error. We’ve listed some common ones in the Examples section.

Examples

C++ string literals are const

C2440 can be caused if you attempt to initialize a non-const char* (or wchar_t*) by using a string literal in C++ code, when the compiler conformance option /Zc:strictStrings is set. In C, the type of a string literal is array of char, but in C++, it’s array of const char. This sample generates C2440:

// C2440s.cpp
// Build: cl /Zc:strictStrings /W3 C2440s.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char [5]'
// to 'char *'
//        Conversion from string literal loses const qualifier (see
// /Zc:strictStrings)

int main() {
   char* s1 = "test"; // C2440
   const char* s2 = "test"; // OK
}

C++20 u8 literals are const char8_t

In C++20 or under /Zc:char8_t, a UTF-8 literal character or string (such as u8'a' or u8"String") is of type const char8_t or const char8_t[N], respectively. This sample shows how compiler behavior changes between C++17 and C++20:

// C2440u8.cpp
// Build: cl /std:c++20 C2440u8.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char8_t [5]'
// to 'const char *'
// note: Types pointed to are unrelated; conversion requires
// reinterpret_cast, C-style cast or function-style cast)

int main() {
   const char* s1 = u8"test"; // C2440 under /std:c++20 or /Zc:char8_t, OK in C++17
   const char8_t* s2 = u8"test"; // OK under /std:c++20 or /Zc:char8_t, C4430 in C++17
   const char* s3 = reinterpret_cast<const char*>(u8"test"); // OK
}

Pointer to member

You may see C2440 if you attempt to convert a pointer to member to void*. The next sample generates C2440:

// C2440.cpp
class B {
public:
   void  f(){;}

   typedef void (B::*pf)();

   void f2(pf pf) {
       (this->*pf)();
       void* pp = (void*)pf;   // C2440
   }

   void f3() {
      f2(f);
   }
};

Cast of undefined type

The compiler emits C2440 if you attempt to cast from a type that’s only forward declared but not defined. This sample generates C2440:

// c2440a.cpp
struct Base { }; // Defined

struct Derived; // Forward declaration, not defined

Base * func(Derived * d) {
    return static_cast<Base *>(d); // error C2440: 'static_cast' : cannot convert from 'Derived *' to 'Base *'
}

Incompatible calling convention

The C2440 errors on lines 15 and 16 of the next sample are qualified with the Incompatible calling conventions for UDT return value message. A UDT is a user-defined type, such as a class, struct, or union. These kinds of incompatibility errors are caused when the calling convention of a UDT specified in the return type of a forward declaration conflicts with the actual calling convention of the UDT and when a function pointer is involved.

In the example, first there are forward declarations for a struct and for a function that returns the struct. The compiler assumes that the struct uses the C++ calling convention. Next is the struct definition, which uses the C calling convention by default. Because the compiler doesn’t know the calling convention of the struct until it finishes reading the entire struct, the calling convention for the struct in the return type of get_c2 is also assumed to be C++.

The struct is followed by another function declaration that returns the struct. At this point, the compiler knows that the struct’s calling convention is C++. Similarly, the function pointer, which returns the struct, is defined after the struct definition. The compiler now knows the struct uses the C++ calling convention.

To resolve C2440 errors caused by incompatible calling conventions, declare functions that return a UDT after the UDT definition.

// C2440b.cpp
struct MyStruct;

MyStruct get_c1();

struct MyStruct {
   int i;
   static MyStruct get_C2();
};

MyStruct get_C3();

typedef MyStruct (*FC)();

FC fc1 = &get_c1;   // C2440, line 15
FC fc2 = &MyStruct::get_C2;   // C2440, line 16
FC fc3 = &get_C3;

class CMyClass {
public:
   explicit CMyClass( int iBar)
      throw()   {
   }

   static CMyClass get_c2();
};

int main() {
   CMyClass myclass = 2;   // C2440
   // try one of the following
   // CMyClass myclass{2};
   // CMyClass myclass(2);

   int *i;
   float j;
   j = (float)i;   // C2440, cannot cast from pointer to int to float
}

Assign zero to interior pointer

C2440 can also occur if you assign zero to an interior pointer:

// C2440c.cpp
// compile with: /clr
int main() {
   array<int>^ arr = gcnew array<int>(100);
   interior_ptr<int> ipi = &arr[0];
   ipi = 0;   // C2440
   ipi = nullptr;   // OK
}

User-defined conversions

C2440 can also occur for an incorrect use of a user-defined conversion. For example, when a conversion operator has been defined as explicit, the compiler can’t use it in an implicit conversion. For more information about user-defined conversions, see User-Defined Conversions (C++/CLI)). This sample generates C2440:

// C2440d.cpp
// compile with: /clr
value struct MyDouble {
   double d;
   // convert MyDouble to Int32
   static explicit operator System::Int32 ( MyDouble val ) {
      return (int)val.d;
   }
};

int main() {
   MyDouble d;
   int i;
   i = d;   // C2440
   // Uncomment the following line to resolve.
   // i = static_cast<int>(d);
}

System::Array creation

C2440 can also occur if you try to create an instance of an array in C++/CLI whose type is a xref:System.Array. For more information, see Arrays. The next sample generates C2440:

// C2440e.cpp
// compile with: /clr
using namespace System;
int main() {
   array<int>^ intArray = Array::CreateInstance(__typeof(int), 1);   // C2440
   // try the following line instead
   // array<int>^ intArray = safe_cast<array<int> ^>(Array::CreateInstance(__typeof(int), 1));
}

Attributes

C2440 can also occur because of changes in the attributes feature. The following sample generates C2440.

// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ];   // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];

Component extensions down casts

The Microsoft C++ compiler no longer allows the const_cast operator to down cast when you compile source code under /clr.

To resolve this C2440, use the correct cast operator. For more information, see Casting operators.

This sample generates C2440:

// c2440g.cpp
// compile with: /clr
ref class Base {};
ref class Derived : public Base {};
int main() {
   Derived ^d = gcnew Derived;
   Base ^b = d;
   d = const_cast<Derived^>(b);   // C2440
   d = dynamic_cast<Derived^>(b);   // OK
}

Conforming template match changes

C2440 can occur because of conformance changes to the compiler in Visual Studio 2015 Update 3. Previously, the compiler incorrectly treated certain distinct expressions as the same type when identifying a template match for a static_cast operation. Now the compiler distinguishes the types correctly, and code that relied on the previous static_cast behavior is broken. To fix this issue, change the template argument to match the template parameter type, or use a reinterpret_cast or C-style cast.

This sample generates C2440:

// c2440h.cpp

template<int *a>
struct S1 {};

int g;
struct S2 : S1<&g> {
};

int main()
{
    S2 s;
    static_cast<S1<&*&g>>(s); // C2440 in VS 2015 Update 3
    // This compiles correctly:
    // static_cast<S1<&g>>(s);
}

This error can appear in ATL code that uses the SINK_ENTRY_INFO macro defined in <atlcom.h>.

Copy-list-initialization

Visual Studio 2017 and later correctly raise compiler errors related to object creation using initializer lists. These errors weren’t caught in Visual Studio 2015 and could lead to crashes or undefined runtime behavior. In C++17 copy-list-initialization, the compiler is required to consider an explicit constructor for overload resolution, but must raise an error if that overload is actually chosen.

The following example compiles in Visual Studio 2015 but not in Visual Studio 2017.

// C2440j.cpp
struct A
{
    explicit A(int) {}
    A(double) {}
};

int main()
{
    const A& a2 = { 1 }; // error C2440: 'initializing': cannot
                         // convert from 'int' to 'const A &'
}

To correct the error, use direct initialization:

// C2440k.cpp
struct A
{
    explicit A(int) {}
    A(double) {}
};

int main()
{
    const A& a2{ 1 };
}

cv-qualifiers in class construction

In Visual Studio 2015, the compiler sometimes incorrectly ignores the cv-qualifier when generating a class object via a constructor call. This defect can potentially cause a crash or unexpected runtime behavior. The following example compiles in Visual Studio 2015 but raises a compiler error in Visual Studio 2017 and later:

struct S
{
    S(int);
    operator int();
};

int i = (const S)0; // error C2440

To correct the error, declare operator int() as const.

I have a base class A and it has a subclass B.
A overrides the + operator and B overrides it as well,calls the parent’s +operator, and casts the result to B. Then I am getting the error message:

error C2440: » : cannot convert from ‘A’
to ‘B’

I thought polymorphism worked in a way that should allow this to work?

iammilind's user avatar

iammilind

67k31 gold badges166 silver badges330 bronze badges

asked Sep 30, 2011 at 18:06

James's user avatar

2

In polymorphism you cannot convert A to B, you can convert B to A. B is a kind of A, but A is NOT a kind of B.

For example, in the classic Shape classes. If you have a class Shape and a class Rectangle that extends [inherit from] Shape, you cannot convert a Shape instance to Rectangle, but you CAN cast a Rectangle to Shape, because it is a ‘kind of’ Shape.

answered Sep 30, 2011 at 18:11

amit's user avatar

amitamit

175k27 gold badges229 silver badges330 bronze badges

5

  • Remove From My Forums
  • Question

  • The following test program is rejected by VS2015 CTP5, of course, but I don’t really understand the error message!

    class Foo;
    
    int main(void) 
    {
    	Foo();
    }
    

    VS2015 CTP5 produces the following output:

    Microsoft (R) C/C++ Optimizing Compiler Version 19.00.22512 for x86
    Copyright (C) Microsoft Corporation.  All rights reserved.

    MySource.cpp(5): error C2440: ‘<function-style-cast>’: cannot convert from ‘initializer-list’ to ‘Foo’
    MySource.cpp(5): note: Source or target has incomplete type

    A similar output is produced by compiler version 19.00.22318 at http://webcompiler.cloudapp.net

    I don’t see any function-style-cast or initializer-list in the source code above here. Is this a compiler bug? If so, should it still be reported to
    https://connect.microsoft.com/VisualStudio ? 

Answers

  • Thank you for your helpful reply, Shu Hu.  Indeed, the error message would have been appropriate if
    Foo() would be changed to Foo({}).

    I just submitted the compiler bug:

    [C++] Incorrect error message, «error C2440: ‘<function-style-cast>’: cannot convert from ‘initializer-list’ to ‘Foo’, note: Source or target has incomplete type»

    https://connect.microsoft.com/VisualStudio/feedbackdetail/view/1121519

    Please check!

    • Marked as answer by

      Friday, February 20, 2015 8:30 AM

Kseni1995

0 / 0 / 1

Регистрация: 03.05.2014

Сообщений: 29

1

06.05.2014, 12:57. Показов 4724. Ответов 11

Метки нет (Все метки)


С++ Не работает программа! Задание было такое: напишите программу invert(p,x,n), возвращающую значение х с инвертированными n-битами, начиная с позиции p ( остальные биты не меняются).

Ввожу, подчеркивает bitset и выдает такую ошибку:
]
1> Ни один конструктор не смог принять исходный тип, либо разрешение перегрузки конструктора неоднозначно
1> error C2440: <function-style-cast>: невозможно преобразовать «unsigned int» в «std::bitset<_Bits>»
1> with
1> [
1> _Bits=32
1> ]
1> Ни один конструктор не смог принять исходный тип, либо разрешение перегрузки конструктора неоднозначно.

Мой код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <bitset>
using namespace std;
unsigned
invert(unsigned x, int p, int n)
{
    int count = sizeof(x) * 8;
    unsigned t = ((unsigned) ~0 << (p - 1)) >> (count - n) << (count - n - p + 1);
    return (~x & t) | (x & ~t);
}
 
int
main()
{
    unsigned x;
    int p, n;
    cout << "Введите x в шестнадцатеричной: ";
    cin >> hex >> x;
    cout << "Введите p позицию и число инвертированных битов n ";
    cin >> dec >> p >> n;
    cout << "Исходный x " << bitset<sizeof(x) * 8>(x) << endl
         << "Инвертированный x " << bitset<sizeof(x) * 8>(invert(x, p, n)) << endl;
    return 0;
}

Подскажите! В чем дело?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Kuzia domovenok

3985 / 3255 / 909

Регистрация: 25.03.2012

Сообщений: 12,102

Записей в блоге: 1

06.05.2014, 14:27

2

С++ Не работает программа! Задание было такое: напишите программу invert(p,x,n), возвращающую значение х с инвертированными n-битами, начиная с позиции p ( остальные биты не меняются).

C++
1
2
3
4
5
6
7
8
int invert(int p, int x, int n){
   int mask=0;
  mask=~mask;
  mask<<=p;
  mask>>=sizeof(int)*8-n;
  mask<<=sizeof(int)*8-n-p;
  return ((~x)&mask)|(x&(~mask));
}



1



0 / 0 / 1

Регистрация: 03.05.2014

Сообщений: 29

06.05.2014, 15:01

 [ТС]

3

Все равно не работает из-за bitset!



0



3254 / 2056 / 351

Регистрация: 24.11.2012

Сообщений: 4,909

06.05.2014, 15:16

4

В исходном виде код компилируется и даже что-то делает (пруф — http://ideone.com/0VYa7s)
Возможные варианты:
1) Вы компилируете не то, что показываете нам;
2) используете какой-нибудь древний компилятор, у которого могут быть свои тараканы.



1



0 / 0 / 1

Регистрация: 03.05.2014

Сообщений: 29

06.05.2014, 18:32

 [ТС]

5

Спасибо! У меня Microsoft Visual C++ 2010 Express. Не знаю, в чем дело…



0



16495 / 8988 / 2205

Регистрация: 30.01.2014

Сообщений: 15,611

06.05.2014, 20:55

6

Цитата
Сообщение от Kseni1995
Посмотреть сообщение

У меня Microsoft Visual C++ 2010 Express.

Ты привел текст ошибки не полностью. Кинь сюда полный текст ошибки.



1



Tulosba

:)

Эксперт С++

4773 / 3267 / 497

Регистрация: 19.02.2013

Сообщений: 9,046

06.05.2014, 21:21

7

Код, демонстрирующий ошибку ТС:

C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
void f(int) {}
void f(unsigned long long) {}
 
int main() {
    
    unsigned int ui;
    f( ui ); // error
    f( static_cast<unsigned long long>(ui) ); // ok
    return 0;
}



1



Kseni1995

0 / 0 / 1

Регистрация: 03.05.2014

Сообщений: 29

07.05.2014, 00:05

 [ТС]

8

Весь текст ошибки:
1>—— Построение начато: проект: новый, Конфигурация: Debug Win32 ——
1> новый.cpp
1>c:usersеленаdocumentsvisual studio 2010projectsновыйновыйновый.cpp(25): error C2440: <function-style-cast>: невозможно преобразовать «unsigned int» в «std::bitset<_Bits>»
1> with
1> [
1> _Bits=32
1> ]
1> Ни один конструктор не смог принять исходный тип, либо разрешение перегрузки конструктора неоднозначно
1>c:usersеленаdocumentsvisual studio 2010projectsновыйновыйновый.cpp(26): error C2440: <function-style-cast>: невозможно преобразовать «unsigned int» в «std::bitset<_Bits>»
1> with
1> [
1> _Bits=32
1> ]
1> Ни один конструктор не смог принять исходный тип, либо разрешение перегрузки конструктора неоднозначно

Добавлено через 1 минуту

Цитата
Сообщение от Tulosba
Посмотреть сообщение

Код, демонстрирующий ошибку ТС:

C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
void f(int) {}
void f(unsigned long long) {}
 
int main() {
    
    unsigned int ui;
    f( ui ); // error
    f( static_cast<unsigned long long>(ui) ); // ok
    return 0;
}

Цитата
Сообщение от Tulosba
Посмотреть сообщение

Код, демонстрирующий ошибку ТС:

И что из этого следует?



0



:)

Эксперт С++

4773 / 3267 / 497

Регистрация: 19.02.2013

Сообщений: 9,046

07.05.2014, 08:41

9

Kseni1995, надо добавить преобразование типа, как в моем коде в 10 строке. Или изменить тип x и invert на unsigned long long.



1



Kseni1995

0 / 0 / 1

Регистрация: 03.05.2014

Сообщений: 29

07.05.2014, 15:07

 [ТС]

10

Цитата
Сообщение от Tulosba
Посмотреть сообщение

Kseni1995, надо добавить преобразование типа, как в моем коде в 10 строке. Или изменить тип x и invert на unsigned long long.

Извините, можете посмотреть мой код еще раз. Я попыталась изменить тип х и invert, но наверно я все равно не так сделала.
Мой код

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "stdafx.h"
#include <iostream> 
#include <bitset> 
using namespace std; 
 
unsigned long long invert(int x, int p, int n)
{
    int count = sizeof(x) * 8;
    for (int i = count - p - n + 1; i <= count - p; ++i) {
        int t = (1 - (x >> i) & 1) << i;
        x &= ~(1 << i);
        x |= t;
    }
    return x;
}
 
int main()
{
    int x;
    int p, n;
    cout << "Введите x в шестнадцатеричной: ";
    cin >> hex >> x;
    cout << "Введите p позицию и число инвертированных битов n ";
    cin >> dec >> p >> n;
    cout << "Исходный x " << bitset<sizeof(x) * 8>(x) << endl
         << "Инвертированный x " << bitset<sizeof(x) * 8>(invert(x, p, n)) << endl;
    return 0;
}

теперь выдает такую ошибку: 1>—— Построение начато: проект: zadacha2_2, Конфигурация: Debug Win32 ——
1> zadacha2_2.cpp
1>LINK : fatal error LNK1123: сбой при преобразовании в COFF: файл недопустим или поврежден
========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========



0



:)

Эксперт С++

4773 / 3267 / 497

Регистрация: 19.02.2013

Сообщений: 9,046

07.05.2014, 15:10

11

Цитата
Сообщение от Kseni1995
Посмотреть сообщение

fatal error LNK1123: сбой при преобразовании в COFF:

Сделайте очистку (Clean) проекта и пересборку (Rebuild).
P.S. код собирабельный под VS2010



0



3985 / 3255 / 909

Регистрация: 25.03.2012

Сообщений: 12,102

Записей в блоге: 1

07.05.2014, 15:10

12

ребилд не помогает?
Инкрементал линкинг задействован?
Project Properties
-> Configuration Properties
-> Linker (General)
-> Enable Incremental Linking -> «No (/INCREMENTAL:NO)»



0



Alright so I’m getting these errors upon compiling… any solution?

c:documents and settingscorymy documentsvisual studio 2008projectstest v1test v1testv1.cpp(19) : error C2440: ‘initializing’ : cannot convert from ‘int’ to ‘const DamagePacketFp’
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>c:documents and settingscorymy documentsvisual studio 2008projectstest v1test v1testv1.cpp(20) : error C2440: ‘initializing’ : cannot convert from ‘int’ to ‘const DWORD *’
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>c:documents and settingscorymy documentsvisual studio 2008projectstest v1test v1testv1.cpp(21) : error C2440: ‘initializing’ : cannot convert from ‘int’ to ‘const BYTE **’
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <windows.h>

#define US_VERSION

#ifndef US_VERSION // JP version
#define DMG_PACKET_PROC 0x45FCC0
#define MONSTER_LIST1 0x8E96F0
#define MONSTER_LIST2 0x9D80E0
#define MONSTER_HP_OFFSET 0xAD64
#else // US version
#define DMG_PACKET_PROC 0x459620
#define MONSTER_LIST1 0x943C48
#define MONSTER_LIST2 0xA327C8
#define MONSTER_HP_OFFSET 0xAD6C
#endif


typedef int (__cdecl * DamagePacketFp)(int, int, int, int, int, int, int);
const DamagePacketFp meleeDamage = DMG_PACKET_PROC;
const DWORD* monsterList1 = MONSTER_LIST1;
const BYTE** monsterList2 = MONSTER_LIST2;

BOOL kill = FALSE;

DWORD CALLBACK ThreadProc(LPVOID lpParam)
{
  DWORD mobID;

  while (1) {
	Sleep(100);
	if (!kill)
	  continue;

	for (mobID = 0; mobID < 0x1F4; mobID++) {
	  if (monsterList1[mobID] == 0)
		continue;

	  if (*(DWORD*)(monsterList2[mobID]+MONSTER_HP_OFFSET) > 0) {
		meleeDamage(1, 1, 1, 0, 0, mobID, 0);
		break;
	  }
	}
  }

  return 1;
}

DWORD CALLBACK HotkeyProc(LPVOID lpParam)
{
  while (1) {
	Sleep(300);
	if (GetAsyncKeyState(VK_F5))
	  kill = !kill;
  }

  return 1;
}

BOOL CALLBACK _DllMainCRTStartup(HINSTANCE hInst, DWORD fdwReason, LPVOID lpvReserved)
{
  if (fdwReason == DLL_PROCESS_ATTACH) {
	if (!CreateThread(NULL, 0, &ThreadProc, NULL, 0, NULL))
	  return FALSE;

	if (!CreateThread(NULL, 0, &HotkeyProc, NULL, 0, NULL))
	  return FALSE;
  }

  return TRUE;
}

Andrey Karpov

Одной из самых распространенных ошибок, с которыми сталкивается программист при переносе приложений с Win32 на Win64 систему, является ошибка, связанная с использованием функции OnTimer. Функции OnTimer используется практически в каждом приложении и высока вероятность, что вы получите несколько ошибок компиляции. Ранее (в Visual Studio 6) эта функция имела прототип «OnTimer(UINT nIDEvent)» и скорее всего так же представлена в пользовательских классах. Сейчас эта функция имеет прототип «OnTimer(UINT_PTR nIDEvent)», что приводит к ошибке компиляции для 64-битной системы.

Рассмотрим стандартный пример:

class CPortScanDlg : public CDialog
{
  ...
  afx_msg void OnTimer(UINT nIDEvent);
  ...
};
BEGIN_MESSAGE_MAP(CPortScanDlg, CDialog)
...
  ON_WM_TIMER()
END_MESSAGE_MAP()

Для данного кода на этапе компиляции будет выдана следующая ошибка:

1>.SrcPortscandlg.cpp(136) : error C2440: 'static_cast' :
cannot convert from 'void (__cdecl CPortScanDlg::* )(UINT)' to
'void (__cdecl CWnd::* )(UINT_PTR)'
1> Cast from base to derived requires dynamic_cast or static_cast

Дело в том, что в макросе ON_WM_TIMER происходит явное приведение типа функции:

#define ON_WM_TIMER() 
{ WM_TIMER, 0, 0, 0, AfxSig_vw, 
  (AFX_PMSG)(AFX_PMSGW) 
  (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT_PTR) > 
    ( &ThisClass :: OnTimer)) },

Приведение успешно выполняется при сборке 32-битной версии, так как типы UINT и UINT_PTR совпадают. В 64-битном режиме это различные типы и приведение типа функции невозможно, отчего и возникает на первый взгляд не очень понятная ошибка компиляции.

Исправить данную ошибку достаточно просто. Необходимо изменить объявление функции OnTimer в пользовательских классах. Пример исправленного кода:

class CPortScanDlg : public CDialog
{
  ...
  afx_msg void OnTimer(UINT_PTR nIDEvent); //Fixed
  ...
};

Иногда в программах функция OnTimer используется неоднократно.

Можно порекомендовать сразу поискать строчку «OnTimer(UINT » и заменить ее на «OnTimer(UINT_PTR «. Также можно воспользоваться множественной заменой, как показано на рисунке 1.

k0011_error_C2440_OnTimer_ru/image1.png

Рисунок 1 — Использование функции «Find and Replace» для исправления объявления функций OnTimer

Не забудьте только, что в обоих случаях в конце строк должен стоять пробел. Этот пробел, к сожалению, не виден на рисунке. Если пробелов не будет, то у вас может получиться «OnTimer(UINT_UINT_PTR nIDEvent)».

Присылаем лучшие статьи раз в месяц

Я пытаюсь создать итератор для реализации связанных списков. Но я получаю сообщение об ошибке. Моя реализация ниже:

#ifndef LinkedListIterative_h
#define LinkedListIterative_h

#include <cstdio>

using std::swap;

template <typename T>
class LinkedList;

template <typename T>
class Iterator;

template<typename T>
class Node
{
    private:
        friend class Iterator<T>;
        friend class LinkedList<T>;        

        T data;
        Node *next;

        Node() : next(nullptr) {}
        Node(const T& data) : data(data) {}
};

template<typename T>
class Iterator
{
    private:
        Node<T> *node;

    public:
        Iterator() : node(nullptr) {}

        Iterator(Node<T> *node) : node(node)  {}

        Iterator(const Node<T> *node) : node(node)  {}

        Iterator(const Iterator& iterator) : node(iterator.node)
        {

        }

        Iterator& operator= (const Iterator& rhs)
        {
            if( this != &rhs )
            {
                node = rhs.node;
            }
        }

        Iterator& operator++()
        {
            node = node->next;

            return *this;
        }

        Iterator& operator+(size_t index)
        {
            while( index-- > 0 && (node != nullptr) )
            {
                ++this;
            }

            return *this;
        }

        Iterator& operator[](size_t index)
        {
            while( index-- > 0 && (node != nullptr) )
            {
                ++this;
            }

            return *this;
        }

        bool operator==(const Iterator &iter)
        {
            return node == iter.node;
        }

        bool operator!=(const Iterator &iter)
        {
            return node != iter.node;
        }

        T& operator*() { return node->data; }

};

template <typename T>
class LinkedList
{
    private:
        size_t size;
        Node<T> *first;
        Node<T> *last;

        Node<T>* createNode(const T &item)
        {
            Node<T> *node = new Node<T>;

            node->data = item;
            node->next = nullptr;

            return node;
        }

        LinkedList(const LinkedList& list){}

        LinkedList& operator=(const LinkedList& list){}

    public:
        typedef Iterator<T> iterator;
        typedef Iterator<const T> const_iterator;

        LinkedList() : size(0), first(nullptr), last(nullptr)
        {

        }

        // Add item at the end of the list
        void add(const T& item)
        {
            Node<T> *node = createNode(item);

            if(first == nullptr)
            {
                first = node;
                last  = node;
            }
            else
            {
                last->next = node;
                last = node;
            }

            ++size;
        }

        void add(const T& item,size_t index)
        {
            if( size == 0 )
            {
                add(item);
            }
            else if( index == 0 && size > 0 )
            {
                addToFirst(item);
            }
            else if( index >= size )
            {
                addToLast(item);
            }
            else
            {
                Node<T> *prev = first;
                Node<T> *curr = first;

                int i = 0;

                while( i++ < index  )
                {
                    prev = curr;
                    curr = curr->next;
                }

                Node<T> *node = createNode(item);

                prev->next = node;
                node->next = curr;

                ++size;
            }
        }

        void addToFirst(const T& item)
        {
            Node<T> *node = createNode(item);

            node->next = first;

            first = node;

            if(size == 0)
                last = node;

            ++size;
        }

        void addToLast(const T& item)
        {
            Node<T> *node = createNode(item);

            last->next = node;

            last = node;

            if(size == 0)
                first = node;

            ++size;
        }

        void removeFirst()
        {
            if( first == nullptr )
                return;

            Node<T> *temp = first;

            first = first->next;

            --size;

            delete temp;

            if( size == 0 )
                last = first;
        }

        void remove(const size_t index)
        {
            if( size == 0 || index > size - 1 )
                throw std::out_of_range("Out of range");

            if(index == 0)
            {
                removeFirst();
                return;
            }

            Node<T> *curr = first;
            Node<T> *prev = first;

            size_t i(0);

            while( i++ < index )
            {
                prev = curr;
                curr = curr->next;
            }

            if( curr == last )
            {
                last = prev;
            }

            prev->next = curr->next;

            delete curr;

            --size;
        }

        void removeLast()
        {
            if( first == nullptr )
                return;

            Node<T> *curr = first;
            Node<T> *prev = first;

            while( curr != last )
            {
                prev = curr;
                curr = curr->next;
            }

            prev->next = nullptr;

            delete last;

            last = prev;

            --size;

            if( size == 0 )
                first = last;
        }

        T& getItem(size_t index) const
        {
            if(index > size)
                throw std::out_of_range("index out of bound!");

            Node<T> *curr = first;

            size_t i = 0;

            while ( i++ != index )
                curr = curr->next;

            return curr->data;
        }

        size_t length() const
        {
            return size;
        }

        iterator begin()
        {
            return iterator(first);
        }

        iterator end()
        {
            return iterator(last); //getting error here
        }

        const_iterator begin() const
        {
            return const_iterator(first);
        }

        const_iterator end() const
        {
            const_iterator(last);
        }

        ~LinkedList()
        {
            Node<T> *curr = first;

            while( curr != last )
            {
                Node<T> *temp = curr;

                curr = curr->next;

                delete temp;
            }
        }           
};


#endif /* LinkedListIterative_h */

Ошибка, которую я получаю:

Error C2440 '<function-style-cast>': cannot convert from 'Node<T> *const ' to 'Iterator<const T>'   

Вызывающий этого внутреннего элемента:

void printList(const LinkedList<int>& list)
{
    size_t index = 0;

    LinkedList<int>::const_iterator iter = list.begin();

    for(; iter != list.end(); ++iter)
    {
        std::cout << *iter << " ";
    }

    while( index < list.length() )
    {
        std::cout << list.getItem(index ++) << " ";
    }

    std::cout << std::endl;
}

Я не могу понять, что случилось.

Here is a template class that enables writing and reading enum class members as strings. It is a simplification of Loki Astari’s design. It avoids the need for helper functions, as suggested by Veski, by using the enable_if<> and is_enum<> templates.

The idea is to replace template <T> with

template <typename T,
    typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>

The consequence is that the operator<<() and operator>>() templates are only instantiated for enums (because of the Substitution Failure Is Not An Error (SFINAE) principle). Then the helper classes enumConstRefHolder and enumRefHolder, and the functions enumToString() and enumFromString(), are no longer needed.

In addition to recognizing an enum member by a string (normalized to be all capital letters), the code recognizes its integer representation. (For the example below, both "FaST" and "1" will be read as Family::FAST.)

EnumIO.h:

#ifndef ENUMIO_H_
#define ENUMIO_H_

#include <algorithm>
#include <ios>
#include <iostream>
#include <sstream>
#include <vector>

// A template class that enables writing and reading enum class
// members as strings.
//
// Author:  Bradley Plohr (2017-05-12)
//
// Note:  The idea to keep the enum names as a static member in a
// template comes from Loki Astari:
//
// https://codereview.stackexchange.com/questions/14309
//         /conversion-between-enum-and-string-in-c-class-header
//
// Usage example:
//
// Enums.h:
// -------
// #ifndef ENUMS_H_
// #define ENUMS_H_
//
// enum class Family { SLOW, FAST };
//
// TODO:  other enum classes
//
// #endif /* ENUMS_H_ */
//
//
// Enums.cc:
// --------
// #include "Enums.h"
// #include "EnumIO.h"
// #include <string>
// #include <vector>
//
// template <>
// const std::vector<std::string>& EnumIO<Family>::enum_names()
// {
//      static std::vector<std::string> enum_names_({ "SLOW", "FAST" });
//      return enum_names_;
// }
//
// TODO:  enum names for other enum classes
//
//
// t_EnumIO.cc:
// -----------
// #include "EnumIO.h"
// #include "Enums.h"
// #include <iostream>
//
// int
// main()
// {
//     Family family;
//
//     family = Family::SLOW;
//     std::cout << family << std::endl;
//
//     std::cin >> family;
//     std::cout << family << std::endl;
//
//     return 0;
// }
//
// For the input
//
//     fAsT
//
// the output is
//
//     SLOW
//     FAST

template <typename T>
class EnumIO
{
public:
    static const std::vector<std::string>& enum_names();
};

template <typename T,
        typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
std::ostream&
operator<<(std::ostream& os, const T& t)
{
    os << EnumIO<T>::enum_names().at(static_cast<int>(t));

    return os;
}

static std::string
toUpper(const std::string& input)
{
    std::string copy(input);
    std::transform(copy.cbegin(), copy.cend(), copy.begin(),
            [](const unsigned char i) { return std::toupper(i); });

    return copy;
}

template <typename T,
        typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
std::istream&
operator>>(std::istream& is, T& t)
{
    std::string input;
    is >> input;
    if (is.fail())
        return is;
    input = toUpper(input);

    // check for a match with a name
    int i = 0;
    for (auto name : EnumIO<T>::enum_names()) {
        if (toUpper(name) == input) {
            // Here we assume that the integer representation of
            // the enum class is the default.  If the enum class
            // members are assigned other integers, this code
            // must be extended by consulting a vector containing
            // the assigned integers.
            t = static_cast<T>(i);

            return is;
        }
        ++i;
    }

    // check for a match with an integer
    int n = static_cast<int>(EnumIO<T>::enum_names().size());
    std::istringstream iss(input);
    int value;
    iss >> value;
    if (not iss.fail() && 0 <= value && value < n) {
        t = static_cast<T>(value); // See the comment above.
        return is;
    }

    is.setstate(std::ios::failbit);

    return is;
}

#endif /* ENUMIO_H_ */

Понравилась статья? Поделить с друзьями:
  • Error c2338 windows headers require the default packing option
  • Error c231 redefinition
  • Error c2259 невозможно создать экземпляр абстрактного класса
  • Error c2248 cannot access private member declared in class
  • Error c2238 непредвиденные лексемы перед