BDE 4.14.0 Production release
Loading...
Searching...
No Matches

Macros

#define BSLSTL_PAIR_NO_IMPLICIT_DELETED_FOR_MOVE_OPS   1
 
#define BSLSTL_PAIR_DO_NOT_DEFAULT_THE_DEFAULT_CONSTRUCTOR   1
 
#define BSLSTL_PAIR_DO_NOT_SFINAE_TEST_IS_SWAPPABLE   1
 

Detailed Description

Outline

Purpose

Provide a simple struct with two members that may use allocators.

Classes

Canonical header: bsl_utility.h

Description

bsl::pair is an allocator-aware version of std::pair. The bsl::pair class template is instantiated on two types, T1 and T2, and provides two public data members, first and second of types T1 and T2, respectively. Each data member might or might not allocate memory using bslma::Allocator. Its interface is identical to std::pair except that it has constructors that take optional allocator arguments to correctly construct the member variables. For example, a bsl::pair<std::string, int> has member first of type std::string and second of type int. A client can pass a bslma::Allocator pointer to the pair constructor and the constructor will pass it through to the first member. Similarly, the copy constructor takes an optional bslma::Allocator pointer and copy-constructs the first member using that allocator.

bsl::pair is unusual in that its data members, first and second, are public. Once constructed, a client program accesses these members directly. This part of the interface is identical to std::pair, for which bsl::pair is intended to be a drop-in replacement.

bsl::pair has four constructors: a default constructor that default-constructs the two data members, a copy constructor that copy-constructs each data member, a constructor taking two arguments of type T1 and T2, which are used to copy-construct first and second respectively, and a conversion constructor template for converting from a bsl::pair of different types, PARAM_1 and PARAM_2, provided PARAM_1 is convertible to T1 and PARAM_2 is convertible to T2. Each constructor also has an optional bslma::Allocator pointer argument. If neither T1 nor T2 use bslma::Allocator, this argument is ignored. Otherwise, either first or second, or both, depending on whether each type uses bslma::Allocator, will be passed the bslma::Allocator* argument during construction. Whether or not a type uses bslma::Allocator is determined by querying the bslma::UsesBslmaAllocator trait for that type. This component also defines a full set of equality and relational operators that can be instantiated if T1 and T2 both provide those operators.

A bsl::pair declares a set of associated type traits that are computed from the type traits of T1 and T2. For each supported type trait, a given specialization of bsl::pair has that trait if and only if both T1 and T2 have that trait. Supported traits are:

Definition bslmf_istriviallycopyable.h:329
Definition bslmf_istriviallydefaultconstructible.h:293
Definition bslmf_isbitwiseequalitycomparable.h:499
Definition bslmf_isbitwisemoveable.h:718

In addition, a bsl::pair specialization has the bslma::UsesBslmaAllocator trait if either T1 or T2 have that trait, or both.

Enhancements Enabled by Modern Language Standards

Language standards after the first (C++98) and its corrigendum (C++03) have added code C++ language features, type traits as well as requirements that affect the exact interface pair provides. This section describes such enhancements as they become available.

Conditional Default Constructor (C++11)

C++11 has introduced type traits, many of which needs compiler backing to be (automatically implementable) and also introduced "defaulted" (special member) functions that generate code without making mistakes. Before C++11 it was not possible to determine if a type had a default constructor in a non-intrusive manner. C++11 makes it possible using <type_traits> to determine that, and = default makes it possible to create special member functions that exists only when they can be implemented properly.

Hence, when using compilers with a reasonably complete implementation of C++11 (notably MSVC 2013 is not one of those) we only implement the default constructor of pair if both types inside the pair type have a default constructor. Note that it means that when using C++11 (except in compilers not implementing it properly) a bsl::pair that stores a reference type (such as int&), or any other type that cannot be default constructed using the syntax T v{}; will cause pair to neither declare nor define a default constructor. So from C++11 onwards a type of bsl::pair<T1, T2> will have a default constructor only if both types T1 and T2 are default constructible. Otherwise, pair will have a default constructor that gives a compile-error (only) if called.

Usage

A bsl::pair is a very simple object when used without allocators. Our usage example concentrates on the use of allocators with bsl::pair. First, we create a utility function that copies a null-terminated string into memory allocated from a supplied allocator:

char *myStrDup(const char *s, bslma::Allocator *basicAllocator)
// Copy the specified null-terminated string 's' into memory allocated
// from the specified 'basicAllocator'
{
char *result = (char*) basicAllocator->allocate(std::strlen(s) + 1);
return std::strcpy(result, s);
}
Definition bslma_allocator.h:457
virtual void * allocate(size_type size)=0

We create a simple string class that holds strings allocated from a supplied allocator. It uses myStrDup (above) in its implementation:

class my_String {
// Simple string class that uses a 'bslma::Allocator' allocator.
bslma::Allocator *d_allocator_p;
char *d_data;
public:
explicit my_String(bslma::Allocator *basicAllocator = 0);
// Construct an empty string using the optionally-specified
// allocator 'basicAllocator'.
my_String(const char* s, bslma::Allocator *alloc = 0); // IMPLICIT
// Construct a string with contents specified in 's' using the
// optionally-specified allocator 'basicAllocator'.
my_String(const my_String& rhs, bslma::Allocator *alloc = 0);
// Construct a copy of the specified 'rhs' string using the
// optionally-specified allocator 'basicAllocator'.
~my_String();
// Destroy this string.
my_String& operator=(const my_String& rhs);
// Copy specified 'rhs' string value to this string.
const char* c_str() const;
// Return the null-terminated character array for this string.
bslma::Allocator *allocator() const;
// Return the allocator used to construct this string or, if no
// allocator was specified at construction, the default allocator
// at the time of construction.
};
bool operator==(const my_String& str1, const my_String& str2)
{
return 0 == std::strcmp(str1.c_str(), str2.c_str());
}
bool operator==(const my_String& str, const char *p)
{
return 0 == std::strcmp(p, str.c_str());
}
bool operator==(const char *p, const my_String& str)
{
return str == p;
}
bool operator!=(const my_String& str1, const my_String& str2)
{
return ! (str1 == str2);
}
bool operator!=(const my_String& str, const char *p)
{
return ! (str == p);
}
bool operator!=(const char *p, const my_String& str)
{
return ! (str == p);
}
bool operator<(const my_String& str1, const my_String& str2)
{
return std::strcmp(str1.c_str(), str2.c_str()) < 0;
}
my_String::my_String(bslma::Allocator *basicAllocator)
: d_allocator_p(bslma::Default::allocator(basicAllocator)), d_data(0)
{
d_data = myStrDup("", d_allocator_p);
}
my_String::my_String(const char *s, bslma::Allocator *basicAllocator)
: d_allocator_p(bslma::Default::allocator(basicAllocator)), d_data(0)
{
d_data = myStrDup(s, d_allocator_p);
}
my_String::my_String(const my_String& rhs,
bslma::Allocator *basicAllocator)
: d_allocator_p(bslma::Default::allocator(basicAllocator)), d_data(0)
{
d_data = myStrDup(rhs.d_data, d_allocator_p);
}
my_String::~my_String()
{
d_allocator_p->deallocate(d_data);
}
my_String& my_String::operator=(const my_String& rhs)
{
if (this != &rhs) {
d_allocator_p->deallocate(d_data);
d_data = myStrDup(rhs.d_data, d_allocator_p);
}
return *this;
}
const char *my_String::c_str() const
{
return d_data;
}
bslma::Allocator *my_String::allocator() const
{
return d_allocator_p;
}
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
bool operator!=(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator<(const MetricId &lhs, const MetricId &rhs)
Definition balxml_encoderoptions.h:68
Definition bslma_usesbslmaallocator.h:343

Our main program creates a mapping from strings to integers. Each node of the mapping consists of a bsl::pair<my_String, int>. The program allocates memory from a test allocator in order to ensure that there are no leaks:

int main()
{
Node *mapping[3];
Definition bslstl_pair.h:1210
Definition bslma_testallocator.h:384

When constructing a Node, an allocator is supplied in addition to parameters for the first and second data members.

{
mapping[0] = new(basicAllocator) Node("One", 1, &basicAllocator);
mapping[1] = new(basicAllocator) Node("Three", 3, &basicAllocator);
mapping[2] = new(basicAllocator) Node("Two", 2, &basicAllocator);
// Temporaries get destroyed here, even on broken compilers.
}
assert("One" == mapping[0]->first);
assert(1 == mapping[0]->second);
assert("Three" == mapping[1]->first);
assert(3 == mapping[1]->second);
assert("Two" == mapping[2]->first);
assert(2 == mapping[2]->second);
assert(6 == alloc.numBlocksInUse());
bsls::Types::Int64 numBlocksInUse() const
Definition bslma_testallocator.h:1087

Clean up at end.

alloc.deleteObjectRaw(mapping[0]);
alloc.deleteObjectRaw(mapping[1]);
alloc.deleteObjectRaw(mapping[2]);
assert(0 == alloc.numBlocksInUse());
return 0;
}
void deleteObjectRaw(const TYPE *object)
Definition bslma_allocator.h:694

Macro Definition Documentation

◆ BSLSTL_PAIR_DO_NOT_DEFAULT_THE_DEFAULT_CONSTRUCTOR

#define BSLSTL_PAIR_DO_NOT_DEFAULT_THE_DEFAULT_CONSTRUCTOR   1

◆ BSLSTL_PAIR_DO_NOT_SFINAE_TEST_IS_SWAPPABLE

#define BSLSTL_PAIR_DO_NOT_SFINAE_TEST_IS_SWAPPABLE   1

◆ BSLSTL_PAIR_NO_IMPLICIT_DELETED_FOR_MOVE_OPS

#define BSLSTL_PAIR_NO_IMPLICIT_DELETED_FOR_MOVE_OPS   1