Large Scale C++ With Modules
Large Scale C++ With Modules
USE-DATE.CXX CALENDAR/DATE.H
#include <iostream> #ifndef CHRONO_DATE_INCLUDED
#include “Calendar/date.h” #define CHRONO_DATE_INCLUDED
#include <iosfwd>
int main() { #include <string>
using namespace Chrono; #include “Calendar/Month.h”
Date date { 22, Month::Sep, 2015 };
std::cout << “Today is “ << date << std::endl; namespace Chrono {
} struct Date {
Date(int, Month, int);
int day() const { return d; }
Month month() const { return m; }
Int year() const { return y; }
private:
int d;
Month m;
int y;
};
#endif // CHRONO_DATE_INCLUDED
USE-DATE.CXX CALENDAR/DATE.CXX
import std.io; import std.io;
import calendar.date; import std.string;
import calendar.month;
int main() {
using namespace Chrono; module calendar.date;
Date date { 22, Month::Sep, 2015 };
std::cout << “Today is “ << date << std::endl; namespace Chrono {
} export
struct Date {
Date(int, Month, int);
int day() const { return d; }
Month month() const { return m; }
Int year() const { return y; }
private:
int d;
Month m;
int y;
};
export
std::ostream& operator<<(std::ostream&, const Date&);
export
std::string to_string(const Date&);
}
USE-DATE.CXX CALENDAR/DATE.CXX
import std.io; import std.io;
import calendar.date; import std.string;
import calendar.month;
int main() {
using namespace Chrono; module calendar.date;
Date date { 18, Month::Sep, 2015 };
std::cout << “Today is “ << date << std::endl; namespace Chrono {
} export
struct Date {
Date(int, Month, int);
int day() const { return d; }
Month month() const { return m; }
Int year() const { return y; }
private:
int d;
Month m;
int y;
};
export
std::ostream& operator<<(std::ostream&, const Date&);
export
Std::string to_string(const Date&);
}
› Well,
#include <iostream>
#include “Calendar/date.h”
int main() {
using namespace Chrono;
Date date { 18, Month::Sep, 2015 };
std::cout << “Today is “ << date << std::endl;
}
int main() {
using namespace Chrono;
Date date { 18, Month::Sep, 2015 };
std::cout << “Today is “ << date << std::endl;
}
int main() {
using namespace Chrono;
Date date { 18, Month::Sep, 2015 };
std::cout << “Today is “ << date << std::endl;
}
100000
% expansion
5
› 1,083,255 bytes with VC++ Dev14
x
0
GCC Clang VC++
#include <iostream>
#include “Calendar/date.h”
#include <iostream>
#include “Calendar/date.h”
› Non Goals:
– Improve or remove the preprocessor
› MS VC 2015 Update 1 Timeframe
– Experimental implementation of the module proposal
– Feedback based on use
– Evidence of feasibility (for C++17)
› MS VC 2015 Update 1 Timeframe
– Experimental implementation of the module proposal
– Feedback based on use
– Evidence of feasibility (for C++17)
} }
Valid programs: (a) 1.cc and 2.cc; (b) 2.cc and 3.cc
20
› What is ODR anyway?
– Bjarne Stroustrup:
› “I asked Dennis when I started in 1979.”
– [DMR]:
› “as if there was exactly one section of source text”
int main() {
using namespace Chrono;
Date date { 18, Month::Sep, 2015 };
std::cout << “Today is “ << date << std::endl;
}
› Collection of related translation units,
with a well-defined set of entry points Module
interface
› Module interface: set of declarations
available to any consumer of a
module Module Unit Module Unit
(implementation)
(implementation)
module calendar.date;
namespace Chrono {
export struct Date {
Date(int, Month, int);
int day() const { return d; }
Month month() const { return m; }
Int year() const { return y; }
private:
int d;
Month m;
int y;
};
module calendar.date;
module calendar.date;
namespace Chrono {
export struct Date {
Date(int, Month, int);
int day() const { return d; }
Month month() const { return m; }
Int year() const { return y; }
private:
int d;
Month m;
int y;
};
#include <iostream>
module Calendar.Month;
namespace Chrono {
export enum class Month { Jan = 1, Feb, Mar, Apr, May, Jun, /*… */ };
#include <iostream>
module Calendar.Month;
namespace Chrono {
export enum class Month { Jan = 1, Feb, Mar, Apr, May, Jun, /*… */ };
Namespace partition
› Strings and bytes
– Name “mangling” or name “decoration”
– Unfortunate leakage to language specification
› Standard “linkage” far behind the practice and needs of
our time
› Examples:
– GCC and Clang support linkage “visibility”
› default
› hidden
› internal
› protected
– VC++ supports:
› dllimport
› dllexport
VC++ ongoing implementation
src.ixx
cl –c /module
Module
metadata
src.obj My.Module.ifc
36
src.cxx
cl –c /module
/module:interface
src.obj My.Module.ifc
37
src.cxx /module:reference My.Module.ifc
cl –c /module
src.obj
38
src.cxx /module:reference AnyFilename
cl –c /module
src.obj
39
› /module
› Turn on module support
› New keywords: module, import, export
› /module:interface
› Force the compiler to interpret source code as module interface
definition
› /module:reference <filename>
› Look for a compiled module interface (IFC) in the file designated by
the path
› /module:search <directory>
› Search directory for referenced files
40
› Can one consume a header file as a module?
– Only if the header file “behaves” well
› /module:export vec.cxx /module:name std.vector
41
› Binary Format Designed to represent C++
– Intended to be open (ideally used by all C++ implementations)
– Recognizable by C++ programmers and implementers alike
– An open-source reference implementation (e.g. on GitHub)
– Compact, efficient, complete
› Structure:
– Set of homogeneous tables representing all relevant entities
– “pointers” are represented by typed indices (all 32-bit wide)
– A “header” describing table locations, size, etc.
– Principle: every index is well typed.
– Deterministically produced by input module source file
› Tooling
– Inspecting; embedding into static LIB or DLL; etc.
– IDE integration
42
.lib .ifc
Questions?