diff --git a/src/include/OpenImageIO/platform.h b/src/include/OpenImageIO/platform.h index 2548d42968..ded9d69e02 100644 --- a/src/include/OpenImageIO/platform.h +++ b/src/include/OpenImageIO/platform.h @@ -527,6 +527,15 @@ #endif +// OIIO_DEVICE_CONSTEXPR is like OIIO_HOSTDEVICE, but it's `constexpr` only on +// the Cuda device side, and merely inline (not constexpr) on the host side. +#ifdef __CUDA_ARCH__ +# define OIIO_DEVICE_CONSTEXPR __device__ constexpr +#else +# define OIIO_DEVICE_CONSTEXPR /*__host__*/ inline +#endif + + // OIIO_PRETTY_FUNCTION gives a text string of the current function // declaration. diff --git a/src/include/OpenImageIO/ustring.h b/src/include/OpenImageIO/ustring.h index c3e6f1a20d..bedadde5c0 100644 --- a/src/include/OpenImageIO/ustring.h +++ b/src/include/OpenImageIO/ustring.h @@ -815,23 +815,41 @@ class OIIO_UTIL_API ustringhash { } /// Construct a ustringhash from a null-terminated C string (char *). - OIIO_HOSTDEVICE explicit ustringhash(const char* str) + OIIO_DEVICE_CONSTEXPR explicit ustringhash(const char* str) { #ifdef __CUDA_ARCH__ - m_hash = Strutil::strhash(str); // GPU: just compute the hash + // GPU: just compute the hash. This can be constexpr! + m_hash = Strutil::strhash(str); #else - m_hash = ustring(str).hash(); // CPU: make ustring, get its hash + // CPU: make ustring, get its hash. Note that ustring ctr can't be + // constexpr because it has to modify the internal ustring table. + m_hash = ustring(str).hash(); +#endif + } + + OIIO_DEVICE_CONSTEXPR explicit ustringhash(const char* str, size_t len) + { +#ifdef __CUDA_ARCH__ + // GPU: just compute the hash. This can be constexpr! + m_hash = Strutil::strhash(len, str); +#else + // CPU: make ustring, get its hash. Note that ustring ctr can't be + // constexpr because it has to modify the internal ustring table. + m_hash = ustring(str, len).hash(); #endif } /// Construct a ustringhash from a string_view, which can be /// auto-converted from either a std::string. - OIIO_HOSTDEVICE explicit ustringhash(string_view str) + OIIO_DEVICE_CONSTEXPR explicit ustringhash(string_view str) { #ifdef __CUDA_ARCH__ - m_hash = Strutil::strhash(str); // GPU: just compute the hash + // GPU: just compute the hash. This can be constexpr! + m_hash = Strutil::strhash(str); #else - m_hash = ustring(str).hash(); // CPU: make ustring, get its hash + // CPU: make ustring, get its hash. Note that ustring ctr can't be + // constexpr because it has to modify the internal ustring table. + m_hash = ustring(str).hash(); #endif } @@ -1013,6 +1031,22 @@ inline ustring::ustring(ustringhash hash) +/// ustring string literal operator +inline ustring operator""_us(const char* str, std::size_t len) +{ + return ustring(str, len); +} + + +/// ustringhash string literal operator +OIIO_DEVICE_CONSTEXPR ustringhash operator""_ush(const char* str, + std::size_t len) +{ + return ustringhash(str, len); +} + + + #if OIIO_VERSION_LESS(3, 0, 0) /// Deprecated -- This is too easy to confuse with the ustringhash class. And /// also it is unnecessary if you use std::hash. This will be removed diff --git a/src/libutil/ustring_test.cpp b/src/libutil/ustring_test.cpp index 9d8d60fd18..9fd77239cc 100644 --- a/src/libutil/ustring_test.cpp +++ b/src/libutil/ustring_test.cpp @@ -156,6 +156,12 @@ test_ustring() // std::hash OIIO_CHECK_EQUAL(std::hash {}(foo), foo.hash()); + + // string literals + auto whichtype = "foo"_us; + OIIO_CHECK_EQUAL(whichtype, ustring("foo")); + OIIO_CHECK_ASSERT((std::is_same::value)); + OIIO_CHECK_ASSERT(!(std::is_same::value)); } @@ -227,6 +233,12 @@ test_ustringhash() // formatting string OIIO_CHECK_EQUAL(Strutil::fmt::format("{}", hfoo), "foo"); + + // string literals + auto whichtype = "foo"_ush; + OIIO_CHECK_EQUAL(whichtype, ustringhash("foo")); + OIIO_CHECK_ASSERT((std::is_same::value)); + OIIO_CHECK_ASSERT(!(std::is_same::value)); }