Zmienne const w instrukcji switch

0

Mam takie coś jako zmienna globalna:

const int jakaszmienna = jakasfunkcja(jakisparametr);

następnie chcę użyć tej stałej w instrukcji switch:

switch(costam)
{
// ...
case jakaszmienna:
    // ...
    break;
// ...
}

natomiast kompilator wywala błędy:

C2051: Case expression not constant
C2131: Expression did not evaluate to a constant

Nie rozumiem o co chodzi. Przecież jakaszmienna jest stałą.

1

Musi być stałą znaną w czasie kompilacji. Więc constexpr albo literał.

0

Niestety moja stała nigdy nie będzie znana w czasie kompilacji. Używam tam funkcji WinAPI: RegisterWindowMessage(L"TaskbarCreated") aby potem użyć tej stałej w procedurze okna. Nie mam pojęcia jak to zrobić

1

To nie możesz użyć do tego switcha. Co konkretnie chcesz zrobić? cośtam i jakiśparametr są dość mało deskryptywne ;​)

0

Używam WinAPI do stworzenia okna. W procedurze okna, zauważyłem że musi być switch. Jak zamieniłem na if-y to mi błąd wywalała funkcja CreateWindowEx().

1

Pokaż więcej kodu, chyba coś robisz bardzo źle.

0

(Uczę się WinAPI)

To mam jako zmienna globalna:

const UINT WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");

Następnie rejestruję okno:

LPCWSTR className = L"MainWindow";

WNDCLASSEX mainWnd;
mainWnd.cbSize = sizeof(WNDCLASSEX);
mainWnd.style = 0;
mainWnd.cbClsExtra = 0;
mainWnd.cbWndExtra = 0;
mainWnd.lpfnWndProc = MainWndProc;
mainWnd.hInstance = hInstance;
mainWnd.hCursor = LoadCursor(NULL, IDC_ARROW);
mainWnd.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
mainWnd.hbrBackground = (HBRUSH)COLOR_WINDOW + 1;
mainWnd.lpszMenuName = NULL;
mainWnd.lpszClassName = className;
mainWnd.hIconSm = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));

if (!RegisterClassEx(&mainWnd))
{
	MessageBox(NULL, L"Cannot register window", L"Error", MB_ICONERROR | MB_OK);
	exit(1);
}

Potem tworzę okno:

MainWndHWND = CreateWindowEx(WS_EX_WINDOWEDGE, className, L"MainWin", WS_POPUP, CW_USEDEFAULT,
	CW_USEDEFAULT, 200, 200, NULL, NULL, hInstance, NULL);

if (MainWndHWND == NULL)
{
	MessageBox(NULL, L"Cannot create window", L"Error", MB_ICONERROR | MB_OK);
	exit(1);
}

A oto MainWndProc():

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_CREATE:
		break;
	case WM_CLOSE:
		DestroyWindow(MainWndHWND);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_TASKBARCREATED: // C2313, C2051
		break;
	default:
		return DefWindowProc(hWnd, msg, wParam, lParam);
	};
	return 0;
}

W tym mój problem. Gdy w MainWndProc() zamieniłem całego switcha na if-y to mi tworzenie okna nie chodzi.

2

Użyj:

typedef LRESULT CALLBACK SomeWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
unordered_map<int,SomeWindowProc*> map;
0

Mógłbyś mi ten kod wytłumaczyć? Nie lubię robić kopiuj-wklej czegoś czego nie rozumiem.

1
#include <unordered_map>
#include <iostream>
using namespace std;

void callById(int i)
{
	typedef void numbers();
	typedef unordered_map<int,numbers*> funmap;
	static const funmap map
	{
		{0,[](){cout<<"zero"<<endl;}},
		{1,[](){cout<<"one"<<endl;}},
		{2,[](){cout<<"two"<<endl;}},
		{3,[](){cout<<"three"<<endl;}},
		{4,[](){cout<<"four"<<endl;}},
		{5,[](){cout<<"five"<<endl;}},
	};
	map.at(i)();
}

int main()
{
	for(int i=0;i<=5;++i) callById(i);
	return 0;
}

Lub może nieco prostsze w zrozumieniu:

#include <unordered_map>
#include <iostream>
using namespace std;

double operation(double a,char op,double b)
{
	typedef double operationfun(double a,double b);
	static const unordered_map<char,operationfun*> map
	{
		{'+',[](double a,double b){ return a+b; }},
		{'-',[](double a,double b){ return a-b; }},
		{'*',[](double a,double b){ return a*b; }},
		{'/',[](double a,double b){ return a/b; }},
	};
	return map.at(op)(a,b);
}

int main()
{
	cout<<operation(3,'*',4)<<endl;
	return 0;
}
0

Niestety, tak jak w przypadku if-ów, okno się nie tworzy po przerobieniu procedury okna na std::unordered_map Nie wiem dlaczego w tej procedurze musi być switch. Gdy zamieniłem std::unordered_map z powrotem na switch ale bez tego WM_TASKBARCREATED, wszystko śmiga. Nie mam pojęcia jak mogę dodać obsługę tego felernego komunikatu...

Z tego co zrozumiałem, to moja procedura okna powinna teraz wyglądać tak:

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	typedef void WndProc();
	static const std::unordered_map<UINT, WndProc*> map
	{
		{WM_CREATE, []() {/* ... */}},
		{WM_DESTROY, []() {/* ... */}},
		// ...
	};
	map.at(msg);
	return 0;
}

Może ja coś źle zrozumiałem.

0

Teraz program wyrzuca wyjątki (wcześniej zapomniałem dodać map.at()):
screenshot-20201207101351.png
screenshot-20201207101431.png
O czym to świadczy? Jak mogę dodać to std::unordered_map coś takiego jak default w switchu?

0

Twoja 'stała' jest zmienna. Więc powinieneś użyć zmiennej, która powinna być moim zdaniem statyczna.



class Program {
 private static UINT WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
0

Wszystko działa już. Dzięki za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1