Skip to content

Commit 3a5a00a

Browse files
authored
fix(dev): Make sure C++ knows ustring & ustringhash are trivially copyable (#4110)
* Use default implementations of copy ctr, destructor, and assignment from ustring. This allows ustring & ustringhash to be recognized as being a variety of flavors of trivially constructible, copyable, and destructible. * It seems that the assignment operators were returning const & whereas it's more typical to return &, so now we do. Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent cfb7918 commit 3a5a00a

File tree

2 files changed

+41
-33
lines changed

2 files changed

+41
-33
lines changed

src/include/OpenImageIO/ustring.h

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,7 @@ class OIIO_UTIL_API ustring {
184184
}
185185

186186
/// Copy construct a ustring from another ustring.
187-
ustring(const ustring& str) noexcept
188-
: m_chars(str.m_chars)
189-
{
190-
}
187+
ustring(const ustring& str) noexcept = default;
191188

192189
/// Construct a ustring from an indexed substring of a ustring.
193190
ustring(const ustring& str, size_type pos, size_type n = npos)
@@ -203,7 +200,7 @@ class OIIO_UTIL_API ustring {
203200
#endif
204201

205202
/// ustring destructor.
206-
~ustring() noexcept {}
203+
~ustring() noexcept = default;
207204

208205
/// Conversion to an OIIO::string_view.
209206
operator string_view() const noexcept { return { c_str(), length() }; }
@@ -212,79 +209,75 @@ class OIIO_UTIL_API ustring {
212209
explicit operator std::string() const noexcept { return string(); }
213210

214211
/// Assign a ustring to *this.
215-
const ustring& assign(const ustring& str)
212+
ustring& assign(const ustring& str)
216213
{
217214
m_chars = str.m_chars;
218215
return *this;
219216
}
220217

221218
/// Assign a substring of a ustring to *this.
222-
const ustring& assign(const ustring& str, size_type pos, size_type n = npos)
219+
ustring& assign(const ustring& str, size_type pos, size_type n = npos)
223220
{
224221
*this = ustring(str, pos, n);
225222
return *this;
226223
}
227224

228225
/// Assign a std::string to *this.
229-
const ustring& assign(const std::string& str)
226+
ustring& assign(const std::string& str)
230227
{
231228
assign(str.c_str());
232229
return *this;
233230
}
234231

235232
/// Assign a substring of a std::string to *this.
236-
const ustring& assign(const std::string& str, size_type pos,
237-
size_type n = npos)
233+
ustring& assign(const std::string& str, size_type pos, size_type n = npos)
238234
{
239235
*this = ustring(str, pos, n);
240236
return *this;
241237
}
242238

243239
/// Assign a null-terminated C string (char*) to *this.
244-
const ustring& assign(const char* str)
240+
ustring& assign(const char* str)
245241
{
246242
m_chars = str ? make_unique(str) : nullptr;
247243
return *this;
248244
}
249245

250246
/// Assign the first n characters of str to *this.
251-
const ustring& assign(const char* str, size_type n)
247+
ustring& assign(const char* str, size_type n)
252248
{
253249
*this = ustring(str, n);
254250
return *this;
255251
}
256252

257253
/// Assign n copies of c to *this.
258-
const ustring& assign(size_type n, char c)
254+
ustring& assign(size_type n, char c)
259255
{
260256
*this = ustring(n, c);
261257
return *this;
262258
}
263259

264260
/// Assign a string_view to *this.
265-
const ustring& assign(string_view str)
261+
ustring& assign(string_view str)
266262
{
267263
m_chars = str.length() ? make_unique(str) : nullptr;
268264
return *this;
269265
}
270266

271267
/// Assign a ustring to another ustring.
272-
const ustring& operator=(const ustring& str) { return assign(str); }
268+
ustring& operator=(const ustring& str) noexcept = default;
273269

274270
/// Assign a null-terminated C string (char *) to a ustring.
275-
const ustring& operator=(const char* str) { return assign(str); }
271+
ustring& operator=(const char* str) { return assign(str); }
276272

277273
/// Assign a C++ std::string to a ustring.
278-
const ustring& operator=(const std::string& str) { return assign(str); }
274+
ustring& operator=(const std::string& str) { return assign(str); }
279275

280276
/// Assign a string_view to a ustring.
281-
const ustring& operator=(string_view str) { return assign(str); }
277+
ustring& operator=(string_view str) { return assign(str); }
282278

283279
/// Assign a single char to a ustring.
284-
const ustring& operator=(char c)
285-
{
286-
return *this = ustring(string_view(&c, 1));
287-
}
280+
ustring& operator=(char c) { return *this = ustring(string_view(&c, 1)); }
288281

289282
/// Return a C string representation of a ustring.
290283
const char* c_str() const noexcept { return m_chars; }
@@ -804,9 +797,10 @@ class OIIO_UTIL_API ustringhash {
804797

805798
/// Copy construct a ustringhash from another ustringhash.
806799
OIIO_HOSTDEVICE constexpr ustringhash(const ustringhash& str) noexcept
807-
: m_hash(str.m_hash)
808-
{
809-
}
800+
= default;
801+
802+
/// Move construct a ustringhash from another ustringhash.
803+
OIIO_HOSTDEVICE ustringhash(ustringhash&& str) noexcept = default;
810804

811805
/// Construct from a ustring
812806
ustringhash(const ustring& str) noexcept
@@ -870,15 +864,12 @@ class OIIO_UTIL_API ustringhash {
870864
}
871865

872866
/// Assign from a ustringhash
873-
OIIO_HOSTDEVICE constexpr const ustringhash&
874-
operator=(const ustringhash& str)
875-
{
876-
m_hash = str.m_hash;
877-
return *this;
878-
}
867+
OIIO_HOSTDEVICE constexpr ustringhash& operator=(const ustringhash& str)
868+
= default;
869+
OIIO_HOSTDEVICE ustringhash& operator=(ustringhash&& str) = default;
879870

880871
/// Assign from a ustring
881-
const ustringhash& operator=(const ustring& str)
872+
ustringhash& operator=(const ustring& str)
882873
{
883874
m_hash = str.hash();
884875
return *this;

src/libutil/ustring_test.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ test_ustring()
7676
ustring foo("foo"), bar("bar"), empty(""), uninit;
7777
ustring foobarbaz("foobarbaz");
7878

79+
OIIO_CHECK_ASSERT(std::is_default_constructible<OIIO::ustring>());
80+
OIIO_CHECK_ASSERT(std::is_trivially_copyable<OIIO::ustring>());
81+
OIIO_CHECK_ASSERT(std::is_trivially_destructible<OIIO::ustring>());
82+
OIIO_CHECK_ASSERT(std::is_trivially_move_constructible<OIIO::ustring>());
83+
OIIO_CHECK_ASSERT(std::is_trivially_copy_constructible<OIIO::ustring>());
84+
OIIO_CHECK_ASSERT(std::is_trivially_move_assignable<OIIO::ustring>());
85+
7986
// Size of a ustring is just a pointer
8087
OIIO_CHECK_EQUAL(sizeof(ustring), sizeof(const char*));
8188

@@ -171,6 +178,16 @@ test_ustringhash()
171178
{
172179
// Two ustrings
173180
ustring foo("foo"), bar("bar");
181+
182+
OIIO_CHECK_ASSERT(std::is_default_constructible<OIIO::ustringhash>());
183+
OIIO_CHECK_ASSERT(std::is_trivially_copyable<OIIO::ustringhash>());
184+
OIIO_CHECK_ASSERT(std::is_trivially_destructible<OIIO::ustringhash>());
185+
OIIO_CHECK_ASSERT(
186+
std::is_trivially_move_constructible<OIIO::ustringhash>());
187+
OIIO_CHECK_ASSERT(
188+
std::is_trivially_copy_constructible<OIIO::ustringhash>());
189+
OIIO_CHECK_ASSERT(std::is_trivially_move_assignable<OIIO::ustringhash>());
190+
174191
OIIO_CHECK_EQUAL(sizeof(ustringhash), sizeof(size_t));
175192

176193
// Make two ustringhash's from strings
@@ -288,7 +305,7 @@ verify_no_collisions()
288305
{
289306
// Try to force a hash collision
290307
parallel_for(int64_t(0), int64_t(1000000LL * int64_t(collide)),
291-
[](int64_t i) { ustring u = ustring::fmtformat("{:x}", i); });
308+
[](int64_t i) { (void)ustring::fmtformat("{:x}", i); });
292309
std::vector<ustring> collisions;
293310
size_t ncollisions = ustring::hash_collisions(&collisions);
294311
OIIO_CHECK_ASSERT(ncollisions == 0);

0 commit comments

Comments
 (0)