Search code examples
c++c++20c++-modulesc++23

Multiple definition error when importing c++23 standard library module in multiple files


I was trying out the c++23 Standard Library Modules (P2465R3) with Visual Studio 17.8.0 Preview 1.0.

When using just the one file everything works as expected and the following compiles and runs:

// main.cpp
import std;

int main() {
    std::print("Hello Modules\n");
}

But once I try to use multiple files I get a linker error:

// test.ixx
export module test;

import std;

export void do_test() {
    std::print("test\n");
}


// main.cpp
import std;
import test;

int main() {
    std::print("Hello Modules\n");
    do_test();
}

LNK2005 "class std::basic_string_view<char,struct std::char_traits<char> > $S3" ?$S3@@3V?$basic_string_view@DU?$char_traits@D@std@@@std@@A) already defined in main.obj

Is this the expected behavior? And if so, how would I go about importing the standard library modules in multiple files?

EDIT: I noticed that I still get the link error even if I replace import std; with import <print>; in both main.cpp and test.ixx, so this is probably an issue with modules as a whole and not just the Standard Library Modules.


Solution

  • I have only begun using import std very recently, so I cannot say for sure, but the problem may be with the implementation of std::print, rather than modules in general.

    At first, I ran the test program exactly as you wrote it. That gave me the same link error as you got. When I eliminated std::print from your test program, however, replacing it with std::cout << std::format, the program ran fine.

    This version uses a module for main.ixx:
    // main.ixx
    export module main;
    
    import std;
    import test;
    
    export int main() {
        std::cout << std::format("Hello Modules\n");
        //std::print("Hello Modules\n");
        do_test();
    }
    
    // test.ixx
    export module test;
    
    import std;
    
    export void do_test() {
        std::cout << std::format("test\n");
        //std::print("test\n");
    }
    
    I also tested without making a module for main:
    // main.cpp
    import std;
    import test;
    
    int main() {
        std::cout << std::format("Hello Modules\n");
        //std::print("Hello Modules\n");
        do_test();
    }
    
    // test.ixx
    export module test;
    
    import std;
    
    export void do_test() {
        std::cout << std::format("test\n");
        //std::print("test\n");
    }
    

    Both versions ran correctly.

    My experiments with import std have generally gone well. They are still at the experimental stage, involving roughly a dozen different modules I have coded. At first, a few of the modules imported individual Standard Library headers, with statements such as import <vector>, and so on. Those did not play well with the modules that used import std. There were weird errors akin to the linker error you encountered. When I switched everything to import std, those errors went away, and it has been clear sailing ever since.

    It is a real plus not to have to figure out over and over again which header file needs to be included where. That alone has left me with a positive feeling about the progress being made with modules.