- The document discusses the use of a sparse_vector class template to simplify logic that uses lookup tables to map error codes to error messages. A sparse_vector provides a node-based representation that only stores non-default elements, saving memory over a standard vector.
- It then explores using a vector to represent a set for fast lookups, by sorting the vector and using binary_search. However, this exposes the workings of the data structure. A flat_set class template is proposed to encapsulate this approach.
- The flat_set implementation is described. It uses a vector to store elements and delegates operations like iteration. Operations like insertion and search use standard algorithms like upper_bound and equal_range along with
Placing a robot on track greatly expands its reach envelope.
-Trackmotion Cycle time: Moving from point A to point B
-Trapezoidal and S- Curve Motion Profiles
The use of the code analysis library OpenC++: modifications, improvements, er...PVS-Studio
The article may be interesting for developers who use or plan to use OpenC++ library (OpenCxx). The author tells about his experience of improving OpenC++ library and modifying the library for solving special tasks.
Talend Open Studio Fundamentals #1: Workspaces, Jobs, Metadata and Trips & Tr...Gabriele Baldassarre
Introduction to Talend Open Studio for Data Integration, focusing on job architecture, metadata, workspaces, connection types and common use components. Rick Tips & Tricks sections
This article demonstrates capabilities of the static code analysis methodology. The readers are offered to study the samples of one hundred errors found in open-source projects in C/C++. All the errors have been found with the PVS-Studio static code analyzer.
Placing a robot on track greatly expands its reach envelope.
-Trackmotion Cycle time: Moving from point A to point B
-Trapezoidal and S- Curve Motion Profiles
The use of the code analysis library OpenC++: modifications, improvements, er...PVS-Studio
The article may be interesting for developers who use or plan to use OpenC++ library (OpenCxx). The author tells about his experience of improving OpenC++ library and modifying the library for solving special tasks.
Talend Open Studio Fundamentals #1: Workspaces, Jobs, Metadata and Trips & Tr...Gabriele Baldassarre
Introduction to Talend Open Studio for Data Integration, focusing on job architecture, metadata, workspaces, connection types and common use components. Rick Tips & Tricks sections
This article demonstrates capabilities of the static code analysis methodology. The readers are offered to study the samples of one hundred errors found in open-source projects in C/C++. All the errors have been found with the PVS-Studio static code analyzer.
Presented at .NET South West (2024-03-26)
https://www.meetup.com/dotnetsouthwest/events/299766807/
One of the greatest shifts in modern programming practices has been how programmers across many different domains, languages and environments have embraced unit testing. Good unit testing, however, is more than waving NUnit at your C# source. Tests help to make long-term product development cost effective rather than a cost centre, they underpin the effective flow of CI/CD and reduce failure demand on a team.
But the discussion of unit testing goes further than simply writing tests: what makes a good unit test? It is not enough to have tests; poor quality tests can hold back development just as good tests can streamline it. This session provides a perspective on what good unit tests (GUTs) can look like with a couple of examples.
Presented at Agile meets Architecture (2023-10-05)
Video at https://www.youtube.com/watch?v=LLEXAdO3X1o
One of the (most overlooked) principles of the Manifesto for Agile Software Development is that "Continuous attention to technical excellence and good design enhances agility". All too often, work that focuses on addressing technical issues is deprioritised in the name of focusing on business value.
Is there a case for technical excellence — in code, in architecture, in people — beyond its appearance on a might-as-well-be-hidden page on a manifesto that's over two decades old? Is technical excellence only the concern of technical roles? Is a good architecture in conflict with business value or a vehicle for it?
This session looks to go beyond buzzwords to build a case for technical excellence that appeals to all roles in a development organisation, noting that "The best architectures, requirements, and designs emerge from self-organizing teams".
Presented online for Build Stuff meetup (https://www.buildstuff.events/events/online-build-stuff-meetup-with-kevlin-henney-and-cassandra-faris)
Whether we are talking about software architecture, coding practices or our development process, it's important to keep it real. All too often we find ourselves attracted to ideas that sound great in theory, but may not work out in practice. All too often we assume we are right — the planned release schedule, the key architectural decisions, the good practices we saw in a blog — but fail to adjust for reality. We fail to acknowledge that our knowledge was incomplete or that the situation has changed, sticking to the plan and practice regardless.
In this talk we will look at what an empirical approach to development means in practice, why it is that up-front architecture is risky and expensive, why it is that most teams who say they're doing agile development are not, and how we can use uncertainty and instability to structure our time and our code.
Presented online for C++ on Sea (2020-07-17)
Video at https://www.youtube.com/watch?v=Bai1DTcCHVE
Lambdas. All the cool kid languages have them. But does lambda mean what C++ and other languages, from Java to Python, mean by lambda? Where did lambdas come from? What were they originally for? What is their relationship to data abstraction?
In this session we will into the history, the syntax, the uses and abuses of lambdas and the way in which lambda constructs in C++ and other languages do (or do not) match the original construct introduced in lambda calculus.
Presented online for javaBin (2020-04-14)
Video at https://www.youtube.com/watch?v=orcSUE0Jjdc
Lambdas. All the cool kid languages have them. But does ‘lambda’ mean what Java, JavaScript, etc. mean by ‘lambda’? Where did lambdas come from? What were they originally for? What is their relationship to data abstraction?
In this session we will look into the history, the syntax and the uses of lambdas and the way in which lambda constructs in Java and other languages do (or do not) match the original construct introduced in lambda calculus.
Presented at DevSum (2018-05-31)
The SOLID principles are often presented as being core to good code design practice. Each of S, O, L, I and D do not, however, necessarily mean what programmers expect they mean or are taught. By understanding this range of beliefs we can learn more about practices for objects, components and interfaces than just S, O, L, I and D.
This talk reviews the SOLID principles and reveals contradictions and different interpretations. It is through paradoxes and surprises we often gain insights. We will leave SOLID somewhat more fluid, but having learnt from them more than expected.
Presented at Foo Café (2019-03-21)
Video at https://www.youtube.com/watch?v=tLSKLLxrZyY
Programmers use coding katas to kick the tyres of their programming languages, paradigms and practices. Typically anchored in a TDD cycle, katas are simple problems that give programmers the opportunity to exercise deliberate practice and explore different approaches, whether programming style, pair programming or test-first programming.
But the simplicity can be deceptive, with many programmers tiring of these katas too soon, missing out on some of the more mind-bending and paradigm-expanding opportunities on offer.
This session will pick on a couple of katas and dig deeper into TDD, lambdas, language(s), (dys)functional programming and Alcubierre drive. It will present code in a variety of languages, highlight the weaknesses of some common mantras, play around with ideas — and blend code, humour and general nerdiness to be both an enjoyable and educational session.
Procedural Programming: It’s Back? It Never Went AwayKevlin Henney
Presented at ACCU Conference 2018 (2018-04-12)
Video at https://www.youtube.com/watch?v=mrY6xrWp3Gs
When programmers describe code as 'procedural', it’s generally not meant as a compliment. There is a belief that we have collectively moved pass such thinking and onto better paradigms. But a paradigm is no more than a pattern language, a family of solutions fit for a context. Change the kind of problem you are solving and you may find a different solution makes sense — even, in these days where pure functions battle it out with classy objects, procedural programming.
This talk takes a look at some of the past, present and future of procedural programming, looking at how there’s more to it than many first assume, how it has informed and continues to influence language design and how it relates to other paradigms, such as functional and OO.
Structure and Interpretation of Test CasesKevlin Henney
Presented at ACCU Cambridge (2018-10-23)
Throw a line of code into many codebases and it's sure to hit one or more testing frameworks. There's no shortage of frameworks for testing, each with their particular spin and set of conventions, but that glut is not always matched by a clear vision of how to structure and use tests — a framework is a vehicle, but you still need to know how to drive. The computer science classic, Structure and Interpretation of Computer Programs, points out that "Programs must be written for people to read, and only incidentally for machines to execute". The same is true of test code.
This talk takes a deep dive into unit testing, looking at examples and counterexamples across a number of languages and frameworks, from naming to nesting, exploring the benefits of data-driven testing, the trade-offs between example-based and property-based testing, how to get the most out of the common given–when–then refrain and knowing how far to follow it.
Keynote present at Agile Tour Vienna (2018-10-06)
Velocity. Sprints. More points, more speed. An obsession with speed often overtakes the core values of agile software development. It’s not just development of software; it’s development of working software. Sprints are not about sprinting; they’re about sustainable pace. Time to market is less important than time in market. Full-stack development is normally a statement about technology, but it also applies to individuals and interactions. The full stack touches both the code and the world outside the code, and with that view comes responsibility and pause for thought. Doing the wrong thing smarter is not smart. The point of a team is its group intelligence not its numbers. Is scaling up the challenge, or is scaling down the real challenge? The distraction and misuse of speed, velocity, point-based systems, time, team size, scale, etc. is not the accelerant of agile development. Agility lies in experimentation, responsiveness and team intelligence.
Keynote presented at NewCrafts (2018-06-18)
Video available at https://vimeo.com/276832516
It has been said that immutability changes everything. But what does that mean in practice? What does it mean for existing code that looks more like the mutant apocalypse than an elegant application of mathematical thinking? Immutability can be an ideal that is hard to reach. Refactoring, on the other hand, is all about the art of the possible. In this talk we'll be clarifying motivation and exploring some approaches to help reducing state mutability in code.
Keynote presented at GOTO Chicago (2018-04-26)
Video available at https://www.youtube.com/watch?v=AbgsfeGvg3E
Everything is changing. Everything is new. Frameworks, platforms and trends are displaced on a weekly basis. Skills are churning.
And yet... Beneath this seemingly turbulent flow there is a slow current, strong and steady, changing relatively little over the decades. Concepts with a long history appear in new forms and fads and technologies. Principles are revisited. Ideas once lost to the mainstream are found again.
In this keynote we revisit the present through the past, looking at the enduring principles that shape programming languages, architecture, development practice and development process, the ideas that cycle round, each time becoming perhaps a little better defined, a little more mature, and look to see what else might be on the horizon.
Presented at SwanseaCon (2017-09-26)
We default to considering systems from an insider's perspective; the view from outside can be quite different. Can we apply this inversion to more than just requirements?
We may say we want testing, but what do we want from testing? We may say we want logging, but what do we want from logging? We may say we want clean code, but what do we want from clean code? We may say we want an agile process, but what do we want from an agile process? These are harder questions, but their answers can make for better solutions.
Presented at .NET South West (2017-07-25)
Code is basically made up of three things: names, spacing and punctuation. With these three tools a programmer needs to communicate intent, and not simply instruct. But if we look at most approaches to naming, they are based on the idea that names are merely labels, so that discussion of identifier naming becomes little more than a discussion of good labelling.
A good name is more than a label; a good name should change the way the reader thinks. A good name should describe structure with intention, as opposed to the affix-heavy approach common to many naming conventions in current use, where the addition of more prefixes and suffixes becomes homeopathic, diluting the meaning. Good naming is part of good design. This session looks at why and what it takes to get a good name.
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Kevlin Henney
Presented at code::dive (2016-11-15)
Video available at https://www.youtube.com/watch?v=brfqm9k6qzc
It is all to easy to dismiss problematic codebases on some nebulous idea of bad practice or bad programmers. Poor code, however, is rarely arbitrary and random in its structure or formulation. Systems of code, well or poorly structured, emerge from systems of practice, whether effective or ineffective. To improve code quality, it makes more sense to pick apart the specific practices and see their interplay — the cause — than to simply focus on the code itself — the effect. This talk looks at how a handful of coding habits, design practices and assumptions can systematically balloon code and compound its accidental complexity.
Thinking Outside the Synchronisation QuadrantKevlin Henney
Presented at code::dive (2016-11-16)
Video available at https://www.youtube.com/watch?v=yl25p91flLY
Ask programmers what comes to mind when you say concurrency and most are likely to say threads. Ask what comes to mind when you say threads and most are likely to say locks or synchronisation. These assumptions are so deeply held that they define and constrain how programmers are taught and think about concurrency: thread safety is almost synonymous with the avoidance of race conditions and the guarded protection of mutable state. But this is only one quadrant of four possibilities, a quadrant diagram partitioned by mutable–immutable along one axis and shared–unshared along another. Modern C++ supports programmers in all four quadrants, not just the synchronisation quadrant. From immutability to actors, this talk will take a look at patterns and practices that encourage thinking and coding outside the locked box.
Presented at GOTO Amsterdam (2017-06-13)
Video available at https://www.youtube.com/watch?v=YyhfK-aBo-Y
What is risk? Many people aren't sure, but it's not just uncertainty: risk is exposure to uncertainty.
Instead of just plastering over the cracks, security should also involve reducing the size and number of cracks, reducing the opportunities for cracks to appear, reducing the class of errors and oversights that can open a system to failure instigated from the outside. We can learn a lot from other kinds of software failure, because every failure unrelated to security can be easily reframed as a security-failure opportunity.
This is not a talk about access control models, authentication, encryption standards, firewalls, etc. This is a talk about reducing risk that lives in the code and the assumptions of architecture, reducing the risk in development practices and in the blind spot of development practices.
Keynote presented at SATURN (2nd May 2017)
Video available at https://www.youtube.com/watch?v=MS3c9hz0bRg
"It's just a detail." Have you ever said that or been told that? Whether it's about implementation or requirements, we often use the word detail to suggest that something is not important enough to worry about. There are so many things to worry about in software development that we need to prioritize—too much detail, not enough focus. The problem is that in software, the details matter because that is what software is: lots of details brought together in combination. If we don't focus on the details, we get debt, defects, and delays.
Presented at Agile Bath & Bristol (21st March 2017)
If software development is a co-operative game, as Alistair Cockburn observed, then what kind of game is Scrum? Lots of people are playing it — or say they are — but there seems to be some disagreement about what the point of the game is, how to play it and even, in many cases, what the rules are. This talk looks at Scrum and other agile approaches through the lens of nomic games, hypothesis-driven development and fun.
Presented at the European Bioinformatics Institute (17th March 2017)
We often talk about good code — that we would like to write it, that there isn't enough of it, that it should not be considered an optional attribute of a codebase. We often talk about it but, when it comes to being precise, we don't always agree what constitutes good code, nor do we necessarily share a common view on its value.
Globus Connect Server Deep Dive - GlobusWorld 2024Globus
We explore the Globus Connect Server (GCS) architecture and experiment with advanced configuration options and use cases. This content is targeted at system administrators who are familiar with GCS and currently operate—or are planning to operate—broader deployments at their institution.
Check out the webinar slides to learn more about how XfilesPro transforms Salesforce document management by leveraging its world-class applications. For more details, please connect with sales@xfilespro.com
If you want to watch the on-demand webinar, please click here: https://www.xfilespro.com/webinars/salesforce-document-management-2-0-smarter-faster-better/
Unleash Unlimited Potential with One-Time Purchase
BoxLang is more than just a language; it's a community. By choosing a Visionary License, you're not just investing in your success, you're actively contributing to the ongoing development and support of BoxLang.
Atelier - Innover avec l’IA Générative et les graphes de connaissancesNeo4j
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Allez au-delà du battage médiatique autour de l’IA et découvrez des techniques pratiques pour utiliser l’IA de manière responsable à travers les données de votre organisation. Explorez comment utiliser les graphes de connaissances pour augmenter la précision, la transparence et la capacité d’explication dans les systèmes d’IA générative. Vous partirez avec une expérience pratique combinant les relations entre les données et les LLM pour apporter du contexte spécifique à votre domaine et améliorer votre raisonnement.
Amenez votre ordinateur portable et nous vous guiderons sur la mise en place de votre propre pile d’IA générative, en vous fournissant des exemples pratiques et codés pour démarrer en quelques minutes.
How Recreation Management Software Can Streamline Your Operations.pptxwottaspaceseo
Recreation management software streamlines operations by automating key tasks such as scheduling, registration, and payment processing, reducing manual workload and errors. It provides centralized management of facilities, classes, and events, ensuring efficient resource allocation and facility usage. The software offers user-friendly online portals for easy access to bookings and program information, enhancing customer experience. Real-time reporting and data analytics deliver insights into attendance and preferences, aiding in strategic decision-making. Additionally, effective communication tools keep participants and staff informed with timely updates. Overall, recreation management software enhances efficiency, improves service delivery, and boosts customer satisfaction.
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Globus
The Earth System Grid Federation (ESGF) is a global network of data servers that archives and distributes the planet’s largest collection of Earth system model output for thousands of climate and environmental scientists worldwide. Many of these petabyte-scale data archives are located in proximity to large high-performance computing (HPC) or cloud computing resources, but the primary workflow for data users consists of transferring data, and applying computations on a different system. As a part of the ESGF 2.0 US project (funded by the United States Department of Energy Office of Science), we developed pre-defined data workflows, which can be run on-demand, capable of applying many data reduction and data analysis to the large ESGF data archives, transferring only the resultant analysis (ex. visualizations, smaller data files). In this talk, we will showcase a few of these workflows, highlighting how Globus Flows can be used for petabyte-scale climate analysis.
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Globus
The U.S. Geological Survey (USGS) has made substantial investments in meeting evolving scientific, technical, and policy driven demands on storing, managing, and delivering data. As these demands continue to grow in complexity and scale, the USGS must continue to explore innovative solutions to improve its management, curation, sharing, delivering, and preservation approaches for large-scale research data. Supporting these needs, the USGS has partnered with the University of Chicago-Globus to research and develop advanced repository components and workflows leveraging its current investment in Globus. The primary outcome of this partnership includes the development of a prototype enterprise repository, driven by USGS Data Release requirements, through exploration and implementation of the entire suite of the Globus platform offerings, including Globus Flow, Globus Auth, Globus Transfer, and Globus Search. This presentation will provide insights into this research partnership, introduce the unique requirements and challenges being addressed and provide relevant project progress.
First Steps with Globus Compute Multi-User EndpointsGlobus
In this presentation we will share our experiences around getting started with the Globus Compute multi-user endpoint. Working with the Pharmacology group at the University of Auckland, we have previously written an application using Globus Compute that can offload computationally expensive steps in the researcher's workflows, which they wish to manage from their familiar Windows environments, onto the NeSI (New Zealand eScience Infrastructure) cluster. Some of the challenges we have encountered were that each researcher had to set up and manage their own single-user globus compute endpoint and that the workloads had varying resource requirements (CPUs, memory and wall time) between different runs. We hope that the multi-user endpoint will help to address these challenges and share an update on our progress here.
Software Engineering, Software Consulting, Tech Lead, Spring Boot, Spring Cloud, Spring Core, Spring JDBC, Spring Transaction, Spring MVC, OpenShift Cloud Platform, Kafka, REST, SOAP, LLD & HLD.
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppGoogle
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
👉👉 Click Here To Get More Info 👇👇
https://sumonreview.com/ai-fusion-buddy-review
AI Fusion Buddy Review: Key Features
✅Create Stunning AI App Suite Fully Powered By Google's Latest AI technology, Gemini
✅Use Gemini to Build high-converting Converting Sales Video Scripts, ad copies, Trending Articles, blogs, etc.100% unique!
✅Create Ultra-HD graphics with a single keyword or phrase that commands 10x eyeballs!
✅Fully automated AI articles bulk generation!
✅Auto-post or schedule stunning AI content across all your accounts at once—WordPress, Facebook, LinkedIn, Blogger, and more.
✅With one keyword or URL, generate complete websites, landing pages, and more…
✅Automatically create & sell AI content, graphics, websites, landing pages, & all that gets you paid non-stop 24*7.
✅Pre-built High-Converting 100+ website Templates and 2000+ graphic templates logos, banners, and thumbnail images in Trending Niches.
✅Say goodbye to wasting time logging into multiple Chat GPT & AI Apps once & for all!
✅Save over $5000 per year and kick out dependency on third parties completely!
✅Brand New App: Not available anywhere else!
✅ Beginner-friendly!
✅ZERO upfront cost or any extra expenses
✅Risk-Free: 30-Day Money-Back Guarantee!
✅Commercial License included!
See My Other Reviews Article:
(1) AI Genie Review: https://sumonreview.com/ai-genie-review
(2) SocioWave Review: https://sumonreview.com/sociowave-review
(3) AI Partner & Profit Review: https://sumonreview.com/ai-partner-profit-review
(4) AI Ebook Suite Review: https://sumonreview.com/ai-ebook-suite-review
#AIFusionBuddyReview,
#AIFusionBuddyFeatures,
#AIFusionBuddyPricing,
#AIFusionBuddyProsandCons,
#AIFusionBuddyTutorial,
#AIFusionBuddyUserExperience
#AIFusionBuddyforBeginners,
#AIFusionBuddyBenefits,
#AIFusionBuddyComparison,
#AIFusionBuddyInstallation,
#AIFusionBuddyRefundPolicy,
#AIFusionBuddyDemo,
#AIFusionBuddyMaintenanceFees,
#AIFusionBuddyNewbieFriendly,
#WhatIsAIFusionBuddy?,
#HowDoesAIFusionBuddyWorks
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxrickgrimesss22
Discover the essential features to incorporate in your Winzo clone app to boost business growth, enhance user engagement, and drive revenue. Learn how to create a compelling gaming experience that stands out in the competitive market.
Large Language Models and the End of ProgrammingMatt Welsh
Talk by Matt Welsh at Craft Conference 2024 on the impact that Large Language Models will have on the future of software development. In this talk, I discuss the ways in which LLMs will impact the software industry, from replacing human software developers with AI, to replacing conventional software with models that perform reasoning, computation, and problem-solving.
Quarkus Hidden and Forbidden ExtensionsMax Andersen
Quarkus has a vast extension ecosystem and is known for its subsonic and subatomic feature set. Some of these features are not as well known, and some extensions are less talked about, but that does not make them less interesting - quite the opposite.
Come join this talk to see some tips and tricks for using Quarkus and some of the lesser known features, extensions and development techniques.
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Shahin Sheidaei
Games are powerful teaching tools, fostering hands-on engagement and fun. But they require careful consideration to succeed. Join me to explore factors in running and selecting games, ensuring they serve as effective teaching tools. Learn to maintain focus on learning objectives while playing, and how to measure the ROI of gaming in education. Discover strategies for pitching gaming to leadership. This session offers insights, tips, and examples for coaches, team leads, and enterprise leaders seeking to teach from simple to complex concepts.
May Marketo Masterclass, London MUG May 22 2024.pdfAdele Miller
Can't make Adobe Summit in Vegas? No sweat because the EMEA Marketo Engage Champions are coming to London to share their Summit sessions, insights and more!
This is a MUG with a twist you don't want to miss.
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Globus
Large Language Models (LLMs) are currently the center of attention in the tech world, particularly for their potential to advance research. In this presentation, we'll explore a straightforward and effective method for quickly initiating inference runs on supercomputers using the vLLM tool with Globus Compute, specifically on the Polaris system at ALCF. We'll begin by briefly discussing the popularity and applications of LLMs in various fields. Following this, we will introduce the vLLM tool, and explain how it integrates with Globus Compute to efficiently manage LLM operations on Polaris. Attendees will learn the practical aspects of setting up and remotely triggering LLMs from local machines, focusing on ease of use and efficiency. This talk is ideal for researchers and practitioners looking to leverage the power of LLMs in their work, offering a clear guide to harnessing supercomputing resources for quick and effective LLM inference.
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Look Me Up Sometime
1. M
Y LAST ARTICLE1
LOOKED AT CONTAINER
indexing, arriving eventually at a class
template, sparse_vector. This had a
similar functional interface to a standard
vector but a representation that was node-based
rather than array-based. Rather than storing all
elements in a sequence consecutively, a sparse_vector
aims to store only elements that are not equal to a given
default filler value.
What use could such a container be? Saving
memory is one obvious application. If you have an
indexable container with a large number of elements
– the majority with the same value – some systems
will benefit from a sparse representation that avoids
holding redundant data instead of a potentially
memory-hungry contiguous representation.
Another use is for simplifying logic, in particular
the replacing of rambling and clumsy selection state-
ments with a lookup-based approach. The following
fragment is based on some code I saw recently:
std::string message;
switch(error)
{
case 0:
message = “No error”;
break;
case 1:
message = “Initialisation failed”;
break;
case 2:
message = “Connection failed”;
break;
case 4:
message = “Connection dropped”;
break;
case 12:
message = “Unknown format”;
break;
case 27:
message = “Memory exhaustion”;
break;
case 67:
message = “Internal error”;
break;
default:
message = “Unknown error”;
break;
}
Elegant? No. Wretched case-and-paste code seems
to litter many systems, fragmenting program flow into
a list of hardwired exceptional cases instead of… well,
something that flows, clearly and smoothly. The
antidote to most rambling switch statements or
cascading if else if statements is to adopt a table-driven
approach.This is more declarative, and as simple and
practical as it is elegant.The only problem in this case
is that the indices are not contiguous. If we were looking
up the number of days in each month, a simple
const array would suffice. But for a 16-bit error
code whose bandwidth is mostly unused, a single array
with 65,336 elements, most of which were initialised
to “Unknown error”, could be considered inept rather
than adept programming.
Using the map container
This is where the standard map container can help out
– hold the significant messages against their error
numbers.This leads to a simple initialisation that can
be kept separate from the error processing code:
std::map<error_code, std::string> messages;
messages[0] = “No error”;
messages[1] = “Initialisation failed”;
messages[2] = “Connection failed”;
messages[4] = “Connection dropped”;
messages[12] = “Unknown format”;
messages[27] = “Memory exhaustion”;
messages[67] = “Internal error”;
The error processing code becomes a little more
direct, but is still hampered a little by the catch-all
for unknown error codes and some moderately
serious syntax:
std::map<error_code, std::string>::iterator found =
messages.find(error);
58 APPLICATION DEVELOPMENT ADVISOR q www.appdevadvisor.co.uk
Kevlin Henney is an
independent software
development consultant
and trainer.He can be
reached at
www.curbralan.com
C++ WORKSHOP
q Standard associative containers are
node-based, sorted hierarchies of linked
elements.
q Random access sequences can be used
as associative containers when they are
sorted.
q New container types can be written that
offer different properties from the
standard containers, but are built from
and encapsulate them.
q The flat_set and flat_multiset class
templates are useful non-standard
commodity types.
FACTS AT A GLANCE
Kevlin Henney explores the relevance of his sparse_vector class template to
simplifying selection statements using lookup tables, and then takes things
further by encapsulating an efficient flat-file structure for lookups
Look me up sometime
2. 60 APPLICATION DEVELOPMENT ADVISOR q www.appdevadvisor.co.uk
C++ WORKSHOP
std::string message =
found != messages.end() ? *found : “Unknown error”;
This is where a sparse_vector can simplify things:
sparse_vector<std::string> messages(“Unknown error”);
messages.resize(65536);
messages[0] = “No error”;
messages[1] = “Initialisation failed”;
messages[2] = “Connection failed”;
messages[4] = “Connection dropped”;
messages[12] = “Unknown format”;
messages[27] = “Memory exhaustion”;
messages[67] = “Internal error”;
Which reduces the original logic to the highly readable:
std::string message = messages[error];
Internally, a sparse_vector is based on a map, but all the special-
case logic is encapsulated within it rather than polluting the
application code. This highlights the fact that encapsulation is not
simply about making data private and is certainly not about
cluttering a class interface with dubious setters and getters. It is more
genuinely concerned with reducing the number of hoops a class
user has to jump through to get a job done.
Sorted
What about the other way around? How about a using a vector for
content-based rather than position-based lookup? Why might such
a need arise? Consider a large set of strings that is read-mostly. Insertions
and removals are not common or are normally grouped together,
and lookup is the most frequent action. For instance, a simple spelling
dictionary is a set that requires fast lookup but does not require
constant updating. This sounds like a job for std::set, which
holds its elements in a sorted tree of individually allocated nodes.
Both lookup and insertion take logarithmic time with respect to
the number of elements in the set. For a dictionary, the majority
of insertions take place during a single phase of the program:
std::ifstream in(“words.txt”);
std::istream_iterator<std::string> begin(in), end;
std::set<std::string> words(begin, end);
...
std::string word;
...
if(!words.count(word))
...
This model of usage means that in exchange for a lot of
dynamic memory activity, most of the benefits of a hierarchically
linked structure are never exercised. A common alternative is to
flatten out the data structure and operate on it manually: popu-
late a random access sequence, such as std::vector or std::deque, with
elements, and use standard algorithmic function templates to sort
and search it:
std::ifstream in(“words.txt”);
std::istream_iterator<std::string> begin(in), end;
std::vector<std::string> words(begin, end);
std::sort(words.begin(), words.end());
words.erase(
std::unique(words.begin(), words.end()),
words.end());
...
std::string word;
...
if(!std::binary_search(words.begin(), words.end(), word))
...
This is a little tedious because it exposes the workings of the data
structure to the whole program.The absence of encapsulation means
that logic will inevitably be duplicated and there is no simple way
to safeguard the invariant – to be a sorted sequence of unique entries
– of the data structure. Sorting is easy enough, but eliminating
duplicates requires the user to remember that the iterator range
is merely reorganised and nothing is actually removed from the
container until the container is told explicitly (this is the same idiom
that is used with std::remove2
).
Flatland
A flattened data structure is useful, but it is crying out to be encap-
sulated. A flat_set class template that supports the same function
interface as std::set, but with slightly different space and speed trade-
offs, is the design goal. The easiest way to score this is first to solve
a slightly simpler problem – that of flat_multiset. Like std::multi-
set it is sorted, but may contain duplicate elements.
As well as offering a useful facility, the implementation of
flat_multiset is a useful exercise in working with the standard
algorithms and the received wisdom on their effective use3
. I
won’t describe or define all the operations for flat_multiset or flat_set
– you can find guidance on what they should be and what is required
of them from the standard or any good STL reference4,5
.
Here is a quick sketch of the outside and inside of flat_multiset:
template<
typename value_type,
typename key_compare = std::less<value_type> >
class flat_multiset
{
...
private:
...
std::vector<value_type> elements;
key_compare comparer;
};
We know the internal representation is going to be based on a
random access sequence and std::vector fulfils this need. The
standard associative containers all take a defaulted parameter
that defines their internal ordering. The default function object
type is std::less, which gives an ascending order, and an instance
is stored for use by the member functions.
Simple construction and assignment require no extra effort to
preserve a sorted order:
template<...>
class flat_multiset
{
public:
explicit flat_multiset(
const key_compare &comparer = key_compare())
: comparer(comparer)
{
}
flat_multiset(
const flat_multiset &other,
const key_compare &comparer = key_compare())
: elements(other.elements), comparer(comparer)
{
}
flat_multiset &operator=(const flat_multiset &rhs)
3. MARCH 2002 61
C++ WORKSHOP
{
elements = rhs.elements;
comparer = rhs.comparer;
return *this;
}
...
};
However, constructing a new flat_multiset from an iterator
range, such as input iterators from a file or inserting a range of elements
into an existing one, requires explicit sorting:
template<...>
class flat_multiset
{
public:
...
template<typename input_iterator>
flat_multiset(
input_iterator begin, input_iterator end,
const key_compare &comparer = key_compare())
: elements(begin, end), comparer(comparer)
{
sort();
}
template<typename input_iterator>
void insert(input_iterator begin, input_iterator end)
{
elements.insert(elements.end(), begin, end);
sort();
}
...
private:
void sort()
{
std::sort(
elements.begin(), elements.end(), comparer);
}
...
};
The private sort member function has been factored out to make
the behaviour clearer, wrapping up the use of the standard sort and
the comparison object. In the case of the insert function, the first
step is to append the new elements following the end of the
existing sequence and then resort the whole lot. There are other
approaches that can be more efficient, but this one is the briefest.
Many of the smaller operations are trivial to implement and just
forward to the corresponding member of the contained std::vector:
template<...>
class flat_multiset
{
public:
...
bool empty() const
{
return elements.empty();
}
void clear()
{
elements.clear();
}
...
};
This simple delegation also applies to many of the typedefs that
the flat_multiset should export. Conveniently enough, this also holds
true for iteration. Many programmers find providing their own
iterator types a little daunting, although when taken one step a time,
the task often turns out to be comparatively simple6
. It doesn’t get
much simpler than for flat_multiset:
template<...>
class flat_multiset
{
public:
...
typedef std::vector<value_type>::const_iterator iterator;
typedef iterator const_iterator;
iterator begin() const
{
return elements.begin();
}
iterator end() const
{
return elements.end();
}
...
};
The contained vector already has iterator types that have all the
right properties; flat_multiset need only reexport them. There is
one caveat, however: iterator access to the set must be const-
only, which is why both iterator and const_iterator are equivalent
to a vector’s const_iterator. A non-const iterator would allow
elements in a sequence to be modified, which could break the
guarantee of a sorted order.
Searching for a value is simple enough when you realise the most
important member function is equal_range, which returns a pair
of iterators, delimiting the upper and lower bound of where the
value occurs or would occur in the sorted range:
template<...>
class flat_multiset
{
public:
...
std::pair<iterator, iterator> equal_range(
const value_type &to_find) const
{
return std::equal_range(
elements.begin(), elements.end(),
to_find, comparer);
}
iterator find(const value_type &to_find) const
{
std::pair<iterator, iterator> found =
equal_range(to_find);
return found.first != found.second ?
found.first : elements.end();
}
std::size_t count(const value_type &to_find) const
{
std::pair<iterator, iterator> found =
equal_range(to_find);
return found.second - found.first;
}
...
};
4. 62 APPLICATION DEVELOPMENT ADVISOR q www.appdevadvisor.co.uk
C++ WORKSHOP
Iterator (pointer) arithmetic makes counting the number of times
a value occurs quite trivial.
So far, so good. But now things become a little hairier. We need
to consider how to insert and erase a single value efficiently. A simplistic
approach to inserting a single element would be to use push_back
to append it to the range and then resort the whole lot. A more
efficient approach is to find the location that the element should
be placed in and shuffle up the elements that follow. Erasing a value
presents a minor challenge because it requires the use of modifi-
able iterators to identify and remove the subrange in which a value
occurs. But these are only minor challenges:
template<...>
class flat_multiset
{
public:
...
iterator insert(const value_type &new_value)
{
return elements.insert(
std::upper_bound(
elements.begin(), elements.end(),
new_value, comparer),
new_value);
}
std::size_t erase(const value_type &to_erase)
{
std::pair<muterator, muterator> found =
std::equal_range(
elements.begin(), elements.end(),
to_erase, comparer);
std::size_t result = found.second - found.first;
elements.erase(found.first, found.second);
return result;
}
...
private:
typedef std::vector<value_type>::iterator muterator;
...
};
The muterator (mutable iterator) typedef is just there to simplify
the code in erase and other member functions that require such
a capability.
Regardless of language, all such algorithmic work is twiddly and
the major challenge sometimes seems to be to read LISP! For pro-
grammers without any experience in functional programming, the
bracketing density appears a little high when using the STL.
That’s the hard work done. The standard tells you which func-
tions are expected of associative containers, the standard library
provides the relevant underlying mechanism and all the resulting
member functions are short, although sometimes a little fiddly.
So, other than the names, what is the minimum change needed
to turn a flat_multiset into a flat_set? Of the functions shown, only
two require changes – the private sort function, which must now
also eliminate duplicates, and the single value insert function, which
must now ensure that duplicates are not introduced.
The sort function sounds innocent enough. Looking back
through the code in the article, you will find a use of unique that
looks like it might solve the problem, leading to the following:
template<...>
class flat_set
{
...
private:
void sort()
{
std::sort(
elements.begin(), elements.end(), comparer);
elements.erase(
std::unique(elements.begin(), elements.end()),
elements.end());
}
...
};
This solution is simple, tempting and, alas, wrong. The out-of-
the-box version of unique uses straightforward equality to cut down
the range.This may or may not match up with the templated sorting
criteria that have been used with the container. In the case of
flat_set<std::string> it will do the right thing because the < and ==
operators will be used and are consistent with one another. How-
ever, if a case-insensitive ordering has been provided as a parameter
to flat_set, equality checking will not eliminate duplicates with the
same spelling but different case.
It transpires that associative containers with unique elements do
not use equality to discard duplicates.They use equivalence, a subtly
different concept, which sometimes gives the same result and some-
times doesn’t. If we consider the ordering of an associative
container to be less-than, then equivalence of two elements is when
neither element is not less-than the other. To make sense of this
construct we can define a helper function object type to perform
this logic for us, using it with the overloaded form of unique that
permits you to pass your own filter function:
template<...>
class flat_set
{
...
private:
class equivalent
{
public:
explicit equivalent(
const key_compare &comparer)
: comparer(comparer)
{
}
bool operator()(
const value_type &lhs,
const value_type &rhs) const
{
return !comparer(lhs, rhs) &&
!comparer(rhs, lhs);
}
private:
key_compare comparer;
};
void sort()
{
std::sort(
elements.begin(), elements.end(), comparer);
elements.erase(
std::unique(
elements.begin(), elements.end(),
equivalent(comparer)),
elements.end());
5. C++ WORKSHOP
}
...
};
The last piece of the jigsaw is insertion of a single element. This
cannot be the same as the one for flat_multiset, or even a slightly
tweaked version of it, because its signature differs.The return value
for single-element insertion into a unique associative container must
indicate whether or not a new value was inserted – a new element
will not be inserted if the value already exists – and an iterator to
either the newly inserted value or the existing value:
template<...>
class flat_set
{
public:
std::pair<iterator, bool> insert(
const value_type &new_value)
{
std::pair<muterator, muterator> found =
std::equal_range(
elements.begin(), elements.end(),
new_value, comparer);
bool exists = found.first != found.second;
iterator result = exists ?
found.first :
elements.insert(found.first, new_value);
return std::make_pair(result, !exists);
}
...
};
In creating a family of types, even one as small as flat_set and
flat_multiset, there are design considerations in addition to performance
and conformance to STL expectations. Copy and paste would be
an inappropriate way to share the common logic between the two
types, as would public inheritance. Private inheritance of flat_multiset
is a possibility but not a particularly fetching one. Factoring out
a common but private base to both flat_set and flat_multiset
would be a cleaner and more decoupled approach. Alternatively,
delegation can be used, either one to another or, better still,
both forwarding to a third implementation type.
The STL is an open framework based on requirements and not sim-
ply a fixed collection of code – some containers and algorithms, plus
hangers on. It is an extensible model that allows you to customise and
introduceyourownabstractions,whichmaybe,asinthecaseofflat_set
and flat_multiset, hybrids of existing concepts and code – the inter-
face of existing types with the implementation of another type.The
flat associative containers have the benefit of space economy and, for
read-mostly use, speed. Balancing these trade-offs is the most com-
mon reason for defining your own commodity types. s
References
1. Kevlin Henney, “Bound and checked”, Application
Development Advisor 6(1), www.appdevadvisor.co.uk
2. Kevlin Henney, “If I had a hammer”, Application
Development Advisor, 5(6), www.appdevadvisor.co.uk
3. Scott Meyers, Effective STL, Addison-Wesley, 2001
4. Matthew Austern, Generic Programming and the STL,
Addison-Wesley, 1999
5. Nicolai Josuttis, The C++ Standard Library,
Addison-Wesley, 1999
6. Kevlin Henney, “Promoting polymorphism”, Application
Development Advisor, 5(8), www.appdevadvisor.co.uk
ADA's free e-mail newsletter
for software developers
By now many of you will have had a free on-line newsletter which is a service to
readers of ADA and packed with the very latest editorial for software and
application developers. However, some of our readers don't get this free service.
If you don't get your free newsletter it's for one of two good reasons.
b
Even though you subscribed to ADA,
you haven't supplied us with your e-mail address.
c
You ticked the privacy box at the time you subscribed
and we can't now send you our newsletter.
Sign up for this free service at www.appdevadvisor.co.uk/subscribe.htm
www.appdevadvisor.co.uk/subscribe.htm