AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻譯準備中
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Stroika is a modern, portable, C++ application framework. It makes writing C++ applications easier by providing safe, flexible, building blocks, as well as wrappers on other useful libraries that help them to all work together more seemlessly.
extern void CallFunction (String);
String a = u8"£50";
// regardless of which way constructed,
// stored internally compactly (in this case 5 bytes for data)
String b = u32" abc ";
CallFunction (a+b);
// trim whitespace, and convert to u16string for some legacy API
std::u16string uuu = (a+b).Trim ().As<u16string>();
// tokenize
String t{ "ABC DEF G" };
Assert (t.Tokenize ()[1] == "DEF");
// most Stroika types automatically support formattable<>
DbgTrace ("v = {}"_f, v); // to a tracelog file, or debugger
cerr << "v = {}"_f (v) << endl; // OR iostreams (unicode mapped automatically)
Similar to c++20 ranges API, but much easier to use (like C# Linq): methods of iterable objects easier to select with smart (e.g. vscode) editor than (std::ranges).
// nb: String is an Iterable<Character>,
// despite internally representing the characters very differently
bool IsAllWhitespace (String s) const
{
return not s.Find ([] (Character c) -> bool { return not c.IsWhitespace (); });
}
Iterable<int> c { 1, 2, 2, 5, 9, 4, 5, 6 };
EXPECT_TRUE (c.Distinct ().SetEquals ({ 1, 2, 4, 5, 6, 9 }));
// Map iterates over 'c' and produces the template argument container
// automatically by appending the result of each lambda application
Iterable<int> c { 3, 4, 7 };
vector<String> vv = c.Map<vector<String>> ([] (int i) { return "{}"_f (i); });
EXPECT_EQ (vv, (vector<String>{"3", "4", "7"}));
// Use Map<> to transform, select subobjects, and filter, and pipe into algorithms like Median
DateTime now = DateTime::Now ();
auto medianDurationOfOpenConnections =
connections.Map<Iterable<Duration>> ([&] (auto c) { return now - c.fCreatedAt; }).Median ();
auto medianDurationOfActiveConnections =
connections
.Map<Iterable<Duration>> ([&] (const auto& c) -> optional<Duration> {
if (c.fActive == false)
return nullopt;
return now - c.fCreatedAt;
})
.Median ();
COW (copy-on-write) often signifcantly improves performance for most common cases (e.g. when one type aggregates another)
APIs organized by access pattern: representational transparency (e.g. Sequence might be implemented as array, linked list, or memory mapped file)
extern void f(Set<int>); // define API in terms of ArchType 'Set<int>'
// use the default Set<> representation - the best for type 'int'
Set<int> s{1, 2, 3};
// as if copy-by-value, but data not actually copied -
// Stroika containers use 'copy-on-write (COW)'
f(s);
s = Concrete::SortedSet_SkipList<int>{s}; // Use a skiplist to represent the set
f(s); // call f the same way regardless of data structure used for implementation
// set equality not order dependent (regardless of data structure)
Assert (s == {2,3,1});
Mapping<int, int> m;
m.Add (3, -3);
m.Add (19, -19);
if (m.Lookup (5)) {
AssertNotReached (); // better not find it
}
Stack<String> stack; // automatically picks data represenation
stack.Push ("hello");
auto r = stack.Pop ();
See Containers Sample for more details; Stroika provides a rich set of container archtypes, and data structure implmentations.
MemoryStream::Ptr<byte> tmpStream = MemoryStream::New<byte> ();
tmpStream.Write (BLOB{...}); // just write binary data to the stream
BinaryToText::Reader::Ptr r = BinaryToText::Reader::New (tmpStream); // optional args for character codes
String asStr = r.ReadAll (); // read that data back as strings
// persist these to file
using namespace IO::FileSystem;
FileOutputStream::Ptr tmpFileStream =
FileOutputStream::New (WellKnownLocations::GetTemporary () / "t.txt");
tmpFileStream.Write (BLOB{});
// or write text
TextToBinary::Writer::New (tmpFileStream/*,optionally specify codepage/conversions/BOM?*/).Write (asStr);
MyClass someObject = ...;
VariantValue v = mapper.FromObject (someObject); // Map object to a VariantValue
// Serialize using any serialization writer defined in
// Stroika::Foundation::DataExchange::Variant (we selected JSON)
Streams::MemoryStream::Ptr<byte> tmpStream = Streams::MemoryStream::New<byte> ();
Variant::JSON::Writer{}.Write (v, tmpStream);
// You can persist these to file if you wish
using namespace IO::FileSystem;
FileOutputStream::Ptr tmpFileStream =
FileOutputStream::New (WellKnownLocations::GetTemporary () / "t.txt");
Variant::JSON::Writer{}.Write (v, tmpFileStream);
Stroika provides a layer on top of the Standard C++ Library, with simpler to use (higher level) classes, more safety checking guarantees (in debug builds), and addressing areas not standardized (such as networking). But those Stroika classes seamlessly integrate with standard C++ classes, and your code can easily use as much of either library as preferences dictate.
Stylistically, Stroika differs from the Standard C++ Library, boost, and many other C++ libraries, in that it (relatively) embraces object oriented abstractions over template-based genericity (see Stroika-Approach-To-Performance.md). The abstraction of type hierarchies is better suited to how people reason, and templates and concepts - while powerful - can be fiddly and obscure programmer intent. Also, Stroika emphasizes separation of interface from implementation: carefully documenting the interface in the headers, and separating the implementation to other files.
Stroika is comprised of 2 layers: the Foundation, which provides building-block classes applicable to most applications, and a series of domain specific Frameworks which provide a rich collection of code in different domains.
The Frameworks depend on the Foundation; Foundation modules frequently depend on each other; but Foundation layer code contains no dependencies outside of the Foundation (except on the Standard C++ Library, and various ThirdPartyComponent libraries optionally included or referenced, like openssl).
Don't want to read - just want to code. Step by step instructions to build your first stroika-based application on your machine, in minutes (less download/compile times - that varies).
Stroika's biggest strength is also its biggest weakness:
Stroika v3 in active development (not stable), and requires C++20 or later.
Stroika v2.1 is stable (in maintainance), and requires C++17 or later. Version 2.1 also conditionally supports many C++20 features (such as three-way-comparison etc, if available).
Stroika v2.0 is very stable, and requires C++14 or later. Stroika v2.0 is used to power a wide variety of open source and commercial applications.
Linux, MacOS, Windows
Stroika v3
Linux (Ubuntu 22.04/24.04/26.04 LTS), Windows 11 (Visual Studio.Net 2022 and 2026), MacOS (XCode 16.4 and 26.3), Raspberry Pi (cross-compiled), and WSL2. g++ 11-16, clang++ 15-22 (against both libstdc++ and libc++).
See Supported Platforms and Compilers for the full matrix.
Stroika v2.1
Tested on x86, arm (+m1), gcc 8 thru gcc 12, clang 6 thru clang 14, Visual Studio.Net 2017, Visual Studio.Net 2019 and Visual Studio.Net 2022, XCode 13, 14, 15.
Stroika v2.0
Tested on x86, arm, gcc 5 thru gcc 8, clang 3 thru clang 6, XCode 8 thru 9.
Github Actions
| Branches | Status | |
|---|---|---|
| v3-Release | .github/workflows/build-N-test.yml | |
| v3-Dev | .github/workflows/build-N-test.yml |
For more details on individual release changes, see:
"Getting Started", build instructions, design and other documentation:
Looking through the samples is also a good way to start:
Please report bugs/issues at:
See Serialization Sample for more details
auto [pk, cert] = Certificate::New (Certificate::SelfSignedCertParams{
.fSubject = {.fCountry = "US"sv, .fOrganization = "ACME Inc"sv, .fCommonName = "localhost"sv}});
auto [fromRawSocket, toRawSocket] = ConnectionOrientedStreamSocket::NewPair (SocketAddress::INET);
Thread::Ptr clientThread{Thread::New (
[&] () {
auto p = Cryptography::SSL::SocketStream::New (fromRawSocket, ClientContext::Options{});
auto writingStream = TextWriter::New (p); // treat byte stream as Character stream
// could select characterset/mapping here
writingStream.Write ("Hello"sv);
writingStream.Close (); // so ReadAll in serverThread knows we are done
},
Thread::eAutoStart, "client"sv)};
Thread::Ptr serverThread{Thread::New (
[&] () {
ServerContext::Options serverOptions{.fCertificate = make_tuple (pk, cert)};
auto p = Cryptography::SSL::SocketStream::New (toRawSocket, serverOptions);
auto readData = TextReader::New (p).ReadAll (); // waits for writer side to close
EXPECT_EQ (readData, "Hello"sv);
},
Thread::eAutoStart, "server"sv)};
Thread::WaitForDone ({clientThread, serverThread});
Route{"variables/(.+)"_RegEx,
// explicit message handler
[this] (Message& m, const String& varName) {
WriteResponse (m.rwResponse (), kVariables_,
kMapper.FromObject (fWSImpl_->Variables_GET (varName)));
}},
Route{HTTP::MethodsRegEx::kPost, "plus"_RegEx,
// automatically map high level functions via ObjectVariantMapper
ObjectRequestHandler::Factory{
kBinaryOpObjRequestOptions_,
[this] (Number arg1, Number arg2) { return fWSImpl_->plus (arg1, arg2); }}},
See WebServices sample for more details.