std::use_facet(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

okay so this is std::use_facet(3) straight out of the C++ Standard Libary manual β€” yes, that's how they spelled it, and we respect the typo πŸ’…

🌟 NAME 🌟

std::use_facet β€” std::use_facet. That's it. That's the name. Short, sweet, iconic.

✨ Synopsis ✨

Defined in header <locale>:

template< class Facet >
const Facet& use_facet( const std::locale& loc );

So what does it do? It obtains a reference to a facet implemented by loc. Bestie, it's giving "give me the facet, I need it now". πŸ’…

But plot twist: the program is ill-formed if Facet is not a facet whose definition contains the public static member id, or if it's a volatile-qualified facet. So like, don't try that, okay? 😭

πŸŽ€ Parameters πŸŽ€

  • loc β€” the locale object to query. That's the one. The locale you're side-eyeing. πŸ‘€

πŸ’– Return value πŸ’–

Returns a reference to the facet. And the reference returned by this function is valid as long as any std::locale object refers to that facet. So it's not forever, but it's valid while the locale is holding on. 🫢

πŸ”₯ Exceptions πŸ”₯

std::bad_cast if std::has_facet<Facet>(loc) == false. So if the locale doesn't have that facet, it's gonna throw. No cap.

🌸 Notes 🌸

Okay bestie, this is important: a std::locale object should not be a temporary if a reference to the Facet object obtained from use_facet is used after the end of statement. Like, the temporary dies and your reference is left dangling. It's giving ghosting, but make it C++. πŸ’€

Here's the BAD example (do not do this):

// BAD:
auto& f = std::use_facet<std::moneypunct<char,
true>>(std::locale{"no_NO.UTF-8"});
foo(f.curr_symbol()); // Error: f internally uses a dangling reference
                      // to a std::locale object that no longer exists.

And here's the GOOD example (slay):

// GOOD:
auto loc = std::locale{"is_IS.UTF-8"}; // OK: a non-temporary object
auto& f = std::use_facet<std::moneypunct<char, true>>(loc);
foo(f.curr_symbol()); // OK: f internally uses a reference to existing
locale object.

Note: I preserved the line breaks exactly as in the original, even the awkward ones, because fidelity is the moment. 😌

πŸ¦‹ Example πŸ¦‹

Display the 3-letter currency name used by the user's preferred locale. Cute, useful, iconic.

// Run this code

#include <iostream>
#include <locale>

int main()
{
    for (const char* name: {"en_US.UTF-8", "de_DE.UTF-8",
"en_GB.UTF-8"})
        std::cout << "Your currency string is "
                  << std::use_facet<std::moneypunct<char,
true>>(std::locale{name}).
                     curr_symbol() << '\n';
}

Output:

Your currency string is USD
Your currency string is EUR
Your currency string is GBP

πŸ‘‘ Defect reports πŸ‘‘

The following behavior-changing defect reports were applied retroactively to previously published C++ standards. So like, they fixed things after the fact. Periodt.

  • LWG 31 β€” Applied to: C++98
    • Behavior as published: the returned reference remained usable as long as the locale value itself exists
    • Correct behavior: the returned reference remains usable as long as some locale object refers to that facet
  • LWG 38 β€” Applied to: C++98
    • Behavior as published: Facet was not required to have a direct member id
    • Correct behavior: required
  • LWG 436 β€” Applied to: C++98
    • Behavior as published: it was unclear whether Facet can be cv-qualified
    • Correct behavior: it can be const-qualified, but not volatile-qualified

🌈 See also 🌈

  • locale β€” set of polymorphic facets that encapsulate cultural differences (class)
  • has_facet β€” checks if a locale implements a specific facet (function template)

Okay that's the whole page! It's from http://cppreference.com, version 2024.06.10, and the manual page is std::use_facet(3). Stay hydrated, bestie, and may your facets never dangle. πŸ’œβœ¨

πŸ“¦ where this page comes from