Using Legacy Header in C++20 Modules with Clang Compiler - c++

I am trying to write some codes in c++20 standard. I write some simple code in c++ module way. And I write '#include <iostream>' because 'import <iostream>' can not be compiled in clang-15.0.2 compiler. Then I meet compile error.
The code is:
// md.ixx
module;
#include <iostream>
export module md;
export int func() {
return 114514;
}
// main.cpp
#include <iostream>
import md;
using namespace std;
int main() {
auto val = func();
cout<<val<<endl;
return 0;
}
Compile error is:
error: main.cpp:10:5: error: missing '#include <iostream>'; 'cout' must be declared before it is used
cout<<val<<endl;
^
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\iostream:40:57: note: declaration here is not visible
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2_IMPORT ostream cout;
^
main.cpp:10:16: error: missing '#include <ostream>'; 'endl' must be declared before it is used
cout<<val<<endl;
^
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\ostream:1000:51: note: declaration here is not visible
basic_ostream<_Elem, _Traits>& __CLRCALL_OR_CDECL endl(
^
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\ostream:269:9: error: missing '#include <xiosbase>'; 'ios_base' must be declared before it is used
ios_base::iostate _State = ios_base::goodbit;
^
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.32.31326\include\xiosbase:170:28: note: declaration here is not visible
class _CRTIMP2_PURE_IMPORT ios_base : public _Iosb<int> { // base class for ios
And If I delete #include<iostream> in file md.ixx. It can be successfully compiled.
So is there any solution to using <iostream> in both main.cpp and md.ixx?
Thank you a lot.

Related

Using automatic conversion in Pybind11

I'm trying to take advantage of some C++ functions by calling them from Python. To do that, I was trying to construct a small demo function to show myself how python types are converted to C++ types. According to the Pybind11 documentation, if you include pybind11/stl.h in your header, automatic conversion should take place for many common types:
https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html
What is wrong with the following code?
my.cpp
#include <vector>
int add_these(std::vector<int> &v) {
int sum=0;
for (int i = 0; i < v.size(); ++i) {
sum += v[i];
}
return sum;
}
wrap.cpp
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
#include "my.cpp"
namespace py=pybind11;
PYBIND11_MODULE(python_example, m) {
m.def("addup", &add_these);
#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
}
I have successfully compiled other demos that I've built, so I don't think it's an error in my compiling process. But compiling this demo I get this error:
wrap.cpp
creating C:\Users\scottjr1\AppData\Local\Temp\pip-req-build-wyi5ezw1\build\lib.win-amd64-3.7
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:c:\users\scottjr1\appdata\python\python37\libs /LIBPATH:c:\users\scottjr1\appdata\python\python37\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\ATLMFC\lib\x64" "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\lib\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\lib\um\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64" /EXPORT:PyInit_python_example build\temp.win-amd64-3.7\Release\src/my.obj build\temp.win-amd64-3.7\Release\src/wrap.obj /OUT:build\lib.win-amd64-3.7\python_example.cp37-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.7\Release\src\python_example.cp37-win_amd64.lib
wrap.obj : error LNK2005: "int __cdecl add_these(class std::vector<int,class std::allocator<int> > &)" (?add_these##YAHAEAV?$vector#HV?$allocator#H#std###std###Z) already defined in my.obj
Creating library build\temp.win-amd64-3.7\Release\src\python_example.cp37-win_amd64.lib and object build\temp.win-amd64-3.7\Release\src\python_example.cp37-win_amd64.exp
build\lib.win-amd64-3.7\python_example.cp37-win_amd64.pyd : fatal error LNK1169: one or more multiply defined symbols found
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\VC\\Tools\\MSVC\\14.16.27023\\bin\\HostX86\\x64\\link.exe' failed with exit status 1169
The problem was simple: header guards don't work on .cpp files so the solution was to break up my.cpp into my.hpp and my.cpp files and include the my.hpp file in the wrap.cpp file.
Of the few demos I've done, this was only required for this demo so far. I'm not sure why breaking up the file is necessary for this demo but not others where I've included the .cpp files directly.
#include "my.cpp" is wrong. Replace with #include "my.h".
my.h should contain:
#include <vector>
int add_these(std::vector<int> const &v);
the declaration of your function.
and my.cpp should contain the definition:
#include "my.h"
int add_these(std::vector<int> const&v) {
int sum=0;
for (int i = 0; i < v.size(); ++i) {
sum += v[i];
}
return sum;
}
the error you are seeing is that you have two .cpp files that contain the definition of the function; that is not allowed in C++.
#include "my.cpp" copy pastes the content of my.cpp where the include directive is. This is not the same as import in python.
This didn't occur in other cases probably because you didn't link the cpp file; regardless including cpp files breaks convention, don't do it.

Using an external class in templated method from dll

I'm trying to use my game engine into an external project. Everything works fine but I have a problem when I'm trying to create a custom component (That inherits from ABhaviour which is an abstract class representing a component that can be activated/disabled).
GameObject.h (exported with __declspec(dllexport))
// [...]
template <typename Class, typename ... Args>
std::shared_ptr<Class> GameObject::AddComponent(Args... args)
{
auto newComp = std::make_shared<Class>(std::forward<Args>(args)...);
m_components[typeid(*newComp).hash_code()] = newComp;
m_components[typeid(*newComp).hash_code()]->SetOwner(*this);
return newComp;
}
// [...]
In an other project (That use my game engine), I'm trying to create the custom ABehaviour :
PlayerController.h
#pragma once
#include <ElkGameEngine/Objects/Components/Behaviours/ABehaviour.h>
class PlayerController :ElkGameEngine::Objects::Components::Behaviours::ABehaviour
{
PlayerController() = default;
~PlayerController() = default;
void Update();
};
After that I add my custom component onto my "Player" GameObject :
Main.cpp
#include <ElkGameEngine/ElkGameEngine.h>
#include <ElkGameEngine/Objects/AObject.h>
#include <ElkGameEngine/Objects/Components/AComponent.h>
#include "PlayerController.h"
using namespace ElkGameEngine::Objects::Components;
using namespace ElkGameEngine::Objects::Components::Behaviours;
int main()
{
ElkGameEngine::Managers::EngineManager elkGameEngine;
elkGameEngine.GetSceneManager()->CreateScene("ElkCraft");
auto& player = elkGameEngine.GetSceneManager()->CreateEmptyGameObject("Player");
player.AddComponent<PlayerController>(); /* Here is the problem */
while (elkGameEngine.IsRunning())
{
elkGameEngine.PreUpdate();
elkGameEngine.PostUpdate();
}
return EXIT_SUCCESS;
}
Visual Studio is unhappy and print me this :
Severity Code Description Project File Line Suppression State
Error C2440 '<function-style-cast>': cannot convert from 'const std::shared_ptr<PlayerController>' to 'std::shared_ptr<ElkGameEngine::Objects::Components::AComponent>' ElkCraft c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory 1472
Error C2228 left of '.swap' must have class/struct/union ElkCraft c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory 1472
Output window :
1>------ Build started: Project: ElkCraft, Configuration: Debug x64 ------
1>Could Not Find C:\Users\adrie\Desktop\GROUP_2\PFA\ElkCraft\*.dll
1>main.cpp
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory(1472): error C2440: '<function-style-cast>': cannot convert from 'const std::shared_ptr<PlayerController>' to 'std::shared_ptr<ElkGameEngine::Objects::Components::AComponent>'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory(1472): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>c:\users\adrie\desktop\group_2\pfa\elkengine\build\elkgameengine\include\elkgameengine\objects\gameobject.h(53): note: see reference to function template instantiation 'std::shared_ptr<ElkGameEngine::Objects::Components::AComponent> &std::shared_ptr<ElkGameEngine::Objects::Components::AComponent>::operator =<PlayerController>(const std::shared_ptr<PlayerController> &) noexcept' being compiled
1>c:\users\adrie\desktop\group_2\pfa\elkengine\build\elkgameengine\include\elkgameengine\objects\gameobject.h(55): note: see reference to function template instantiation 'std::shared_ptr<ElkGameEngine::Objects::Components::AComponent> &std::shared_ptr<ElkGameEngine::Objects::Components::AComponent>::operator =<PlayerController>(const std::shared_ptr<PlayerController> &) noexcept' being compiled
1>c:\users\adrie\desktop\group_2\pfa\elkcraft\sources\main.cpp(18): note: see reference to function template instantiation 'std::shared_ptr<PlayerController> ElkGameEngine::Objects::GameObject::AddComponent<PlayerController,>(void)' being compiled
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory(1472): error C2228: left of '.swap' must have class/struct/union
1>Generating Code...
1>Compiling...
1>PlayerController.cpp
1>Generating Code...
1>Done building project "ElkCraft.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I think that the problem come from the fact that my game engine (Which is a group of DLL) is exporting a templated method (AddComponent and other ones like GetComponent).
Is it possible to use a templated method from a dll with a class/struct template argument from the project using the dll ?
Am I doing something wrong ?
Do I need to specify something on my PlayerController to make it "known/usable" in the AddComponent method ?

Compilation error: `error: definition of implicitly-declared`

I am trying to create a class which calls one of it's functions when created, but I am getting the following error when compiling:
g++ -std=c++11 -Wall -Wextra -Werror -pedantic-errors -DNDEBUG -c src/PuzzleSolution.cpp
src/PuzzleSolution.cpp:7:32: error: definition of implicitly-declared 'PuzzleSolution::PuzzleSolution()'
PuzzleSolution::PuzzleSolution()
^
src/PuzzleSolution.cpp:12:6: error: prototype for 'void PuzzleSolution::addRow()' does not match any in class 'PuzzleSolution'
void PuzzleSolution::addRow()
^
src/PuzzleSolution.h:19:10: error: candidate is: void PuzzleSolution::addRow(std::vector<unsigned int>&)
explicit PuzzleSolution();
^
src/PuzzleSolution.cpp:17:48: error: no 'void PuzzleSolution::addElement(unsigned int)' member function declared in class 'PuzzleSolution'
void PuzzleSolution::addElement(unsigned int id)
^
make: *** [PuzzleSolution.o] Error 1
Here is the header:
#include <vector>
using namespace std;
class PuzzleSolution {
private:
vector<vector<unsigned int>> sol;
public:
explicit PuzzleSolution();
void addRow();
};
Here is the cpp file:
#include "PuzzleSolution.h"
PuzzleSolution::PuzzleSolution()
{
addRow();
}
void PuzzleSolution::addRow()
{
this->sol.emplace_back();
}
What am I doing wrong?
The code as it is has no error. It compiles with GCC 4.8.2
Be sure that your header file is indeed what you have linked to. Most likely the header being included is different than the one you have actually posted here.
Side Note: Generally it is considered as a bad practice to put using namespace std; in a header file.
Found the issue:
There was a file in the src folder called PuzzleSolution.h.gch
#Quatin and #StoryTeller helped me to understand that this is a pre-compiled header, which the compiler kept using.
Once deleted, the project compiled and executed

Mutually dependent classes and inheritance

I'm working on a little C++ WinAPI wrapper. I'd like to create my own window and append my own controls to it.
I created 2 classes : Window and Control.
The problem is that I struggle to deal with the multiple header files, because the class Control needs the class Window and vice versa. When I compile my code, I get many errors..
Here are my files :
globals.h :
// globals.h
// I need this file to define a few constants and to include the main headers needed by my classes
#ifndef GLOBALS_H
#define GLOBALS_H
#include <windows.h>
#include <iostream>
#include <vector>
#include "window.h"
#define SOME_GLOBAL_CONSTANT 1
#endif
window.h :
// window.h
#ifndef WINDOW_H
#define WINDOW_H
#include "globals.h"
#include "control.h"
class Window
{
public:
Window(RECT windowRect);
virtual ~Window();
void appendChild(Control* child);
private:
RECT m_windowRect;
Control m_staticBackground;
std::vector<Control*> m_children;
};
#endif
window.cpp :
// window.cpp
#include "window.h"
Window::Window(RECT windowRect) : m_windowRect(windowRect)
{
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
}
Window::~Window()
{
m_children.clear();
}
void Window::appendChild(Control* child)
{
m_children.push_back(child);
}
control.h :
// control.h
#ifndef CONTROL_H
#define CONTROL_H
#include "globals.h"
class Control
{
public:
Control(Window* parentWindow);
virtual ~Control();
private:
RECT m_controlRect;
Window* m_parentWindow;
};
#endif
control.cpp :
// control.cpp
#include "control.h"
Control::Control(Window* parentWindow) : m_controlRect({}), m_parentWindow(parentWindow)
{
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
}
Control::~Control()
{}
And finally, main.cpp :
#include "globals.h"
class MyCustomControl : public Control
{
public:
MyCustomControl(Window* parentWindow) : Control(parentWindow)
{}
~MyCustomControl()
{}
};
class MyWindow : public Window
{
public:
MyWindow(RECT windowRect) : Window(windowRect)
{
kid1 = new MyCustomControl(this);
appendChild(kid1);
}
~MyWindow()
{
delete kid1;
}
private:
MyCustomControl* kid1;
};
int main()
{
MyWindow appWindow;
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
return 0;
}
Here are all the compilation errors I get :
1>------ Build started: Project: include, Configuration: Debug Win32 ------
1>window.cpp
1>d:\visual studio 2017\projects\include\include\control.h(9): error C2061: syntax error: identifier 'Window'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2143: syntax error: missing ';' before '*'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2238: unexpected token(s) preceding ';'
1>main.cpp
1>d:\visual studio 2017\projects\include\include\control.h(9): error C2061: syntax error: identifier 'Window'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2143: syntax error: missing ';' before '*'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2238: unexpected token(s) preceding ';'
1>d:\visual studio 2017\projects\include\include\main.cpp(8): error C2664: 'Control::Control(const Control &)': cannot convert argument 1 from 'Window *' to 'const Control &'
1>d:\visual studio 2017\projects\include\include\main.cpp(8): note: Reason: cannot convert from 'Window *' to 'const Control'
1>d:\visual studio 2017\projects\include\include\main.cpp(8): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>d:\visual studio 2017\projects\include\include\main.cpp(32): error C2512: 'MyWindow': no appropriate default constructor available
1>d:\visual studio 2017\projects\include\include\main.cpp(13): note: see declaration of 'MyWindow'
1>control.cpp
1>d:\visual studio 2017\projects\include\include\window.h(13): error C2061: syntax error: identifier 'Control'
1>d:\visual studio 2017\projects\include\include\window.h(17): error C3646: 'm_staticBackground': unknown override specifier
1>d:\visual studio 2017\projects\include\include\window.h(17): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\visual studio 2017\projects\include\include\window.h(18): error C2065: 'Control': undeclared identifier
1>d:\visual studio 2017\projects\include\include\window.h(18): error C2059: syntax error: '>'
1>d:\visual studio 2017\projects\include\include\window.h(18): error C2976: 'std::vector': too few template arguments
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\vector(700): note: see declaration of 'std::vector'
1>Generating Code...
1>Done building project "include.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Any help would be greatly appreciated.
Thank you in advance,
winapiwrapper.
Edit: I have also read this thread, but I couldn't solve my problem.
Welcome to programming. Strike down one error message and two shall take its place.
Well... Not really. What's happening is as you resolve one error, this reveals the errors that the precious errors were hiding.
First a PSA:
Don't write much code without compiling and testing. This way you have a smaller amount of code you need to check when something goes wrong. Start with a main function. Make sure it builds. Add the headers you need. Make sure it builds. Write a function for main to call. Make sure it builds. Repeat until program is finished. Trying to add too much all at once results in cascading storms of errors like you have experienced here.
Global include header files are usually a sucker bet. They often lead you into problems like the circular dependency you have here and make files include everything even when they don't have to. This can slow down build times.
Next, read the following link before continuing: Resolve header include circular dependencies
Now on with the answer:
window.h includes control.h. control .h includes window.h though global.h. This results in the Chicken and egg problem discussed in the above link. One of the headers is going to be included before the other and not be able to find the contents of the other file. Fortunately control.h only needs a reference to Window, not the whole thing, and this can be satisfied with a forward declaration and removing the global include file.
I'm not going to demonstrate cleaning this up. The process is well documented in the link.
This exposes hydra head number 2: Window contains Control m_staticBackground and does not explicitly initialize it. This results in the compiler hunting around for a default constructor for Control, something that does not exist.
Solution: Explicitly initialize m_staticBackground
Window::Window(RECT windowRect) : m_windowRect(windowRect),
m_staticBackground(this)
{
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
}
BIG Mother Freaking note here: m_staticBackground(this) is dodgy as hell. this has not been fully constructed yet, so if you do more than simply store it in Control::Control (which is all you are currently doing) very bad, unpredictable things can happen. Do not use parentWindow or m_parentWindow inside the body of the Control constructor. If possible find a better, safer, way to do this. If not possible, document it with DO NOT USE messages to remind your future self or anyone else looking at the code not to use them.
Once this has been fixed you get to
MyWindow appWindow;
over in main. MyWindow's constructor requires a RECT you don't currently have a RECT to provide, so I'll stop here.
Move "window.h" from globals.h to controls.cpp. And put class Window; before class Controls { in controls.h. This is called forward declaration.
You even do not need window.h in controls.cpp, you can move it directly to your main.cpp.

co_await not working

I attempted to try out co_await as mentioned in this article https://blogs.msdn.microsoft.com/vcblog/2016/04/04/using-c-coroutines-to-simplify-async-uwp-code/ but there are weird compilation errors:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\experimental\resumable(44,0): Error C2825: '_Ret': must be a class or namespace when followed by '::' (compiling source file MainPage.xaml.cpp)
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\experimental\resumable(44): error C2825: '_Ret': must be a class or namespace when followed by '::' (compiling source file MainPage.xaml.cpp)
MainPage.xaml.cpp(44): note: see reference to class template instantiation 'std::experimental::coroutine_traits<void,::MainPage ^,Windows::UI::Xaml::Navigation::NavigationEventArgs ^>' being compiled
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\experimental\resumable(44,0): Error C2510: '_Ret': left of '::' must be a class/struct/union (compiling source file MainPage.xaml.cpp)
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\experimental\resumable(44): error C2510: '_Ret': left of '::' must be a class/struct/union (compiling source file MainPage.xaml.cpp)
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\experimental\resumable(44,0): Error C2061: syntax error: identifier 'promise_type' (compiling source file MainPage.xaml.cpp)
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\experimental\resumable(44): error C2061: syntax error: identifier 'promise_type' (compiling source file MainPage.xaml.cpp)
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\experimental\resumable(44,0): Error C2238: unexpected token(s) preceding ';' (compiling source file MainPage.xaml.cpp)
Originally, I put the following code in the constructor
#include <experimental\resumable>
#include <pplawait.h>
using namespace concurrency;
MainPage::MainPage()
{
InitializeComponent();
auto my_data_file = co_await Windows::ApplicationModel::Package::Current->InstalledLocation->GetFileAsync("samples.txt");
// Preparing app data structures
}
which does not work. My guess is that this is not possible in constructor (for obvious reason) so I move the co_await line to
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
auto my_data_file = co_await Windows::ApplicationModel::Package::Current->InstalledLocation->GetFileAsync("samples.txt");
}
which result in the aforementioned compilation errors.
My guess is that the first problem is that you can't return void from a resumable function since void does not fill any coroutine traits that co_await expect (like get_return_object , set_result etc.)
if you are already using PPL, return task<void>:
task<void> MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
auto my_data_file = co_await Windows::ApplicationModel::Package::Current->InstalledLocation->GetFileAsync("samples.txt");
}
I found the answer: co_await can only be used if we are returning a task<> (this is incorrect, see #DavidHaim's answer). I guess it is just a syntactic sugar for create_task. The solution is to extract a method returning task<void> in this case:
#include <experimental\resumable>
#include <pplawait.h>
using namespace concurrency;
MainPage::MainPage()
{
InitializeComponent();
PrepareData();
}
task<void> MainPage::PrepareData()
{
auto my_data_file = co_await Windows::ApplicationModel::Package::Current->InstalledLocation->GetFileAsync("samples.txt");
// Preparing app data structures
}
Some comment: Although the coroutine feature looks nice, it pollutes the language. Observe that the body of PrepareData() does NOT have any return statement but the signature says it returns task<void>, leading to my failure to recognize the requirement in the article.