Date: Tue, 20 May 2025 13:07:19 +0100
On Tue, May 20, 2025 at 9:02 AM Jonathan Wakely wrote:
>
>
> If the function body is empty then it can typically be a variable template or an alias template.
> Or have no function body at all. You don't need to define it if you're not calling it.
I didn't realise that my previous code would compile and link
successfully without a body, that's cool.
But then there's times when a body is needed, like in the following
function. (Note in places that I had to use *((A*)nullptr) instead of
'declval' because the compiler refused to compile it). You can
dereference a null pointer in a non-evaluated context, it's fine.
#include <type_traits> // is_same, remove_cvref
#include <utility> // declval
template<class ExcludedTypezzz, class Azzz, class Bzzz, class Czzz>
consteval decltype(auto) GetType(Azzz&&, Bzzz&&, Czzz&&) noexcept
{
using std::declval, std::is_same_v, std::remove_cvref_t;
typedef remove_cvref_t<Azzz> A;
typedef remove_cvref_t<Bzzz> B;
typedef remove_cvref_t<Czzz> C;
typedef remove_cvref_t<ExcludedTypezzz> ExcludedType;
constexpr auto is_valid = []<typename ExcludedType2, typename
T>(void) consteval noexcept -> bool
{
if constexpr ( !requires { declval<typename
T::value_type2>(); } ) return false;
else if constexpr ( is_same_v< typename T::value_type2,
void > ) return false;
else if constexpr ( is_same_v< typename T::value_type2,
ExcludedType > ) return false;
else return true;
};
if constexpr ( is_valid.template
operator()<ExcludedType,A>() ) return *(A*)nullptr;
else if constexpr ( is_valid.template
operator()<ExcludedType,B>() ) return *(B*)nullptr;
else if constexpr ( is_valid.template
operator()<ExcludedType,C>() ) return *(C*)nullptr;
else if constexpr ( requires { declval<A&>().begin(); } ) {
return ((A*)nullptr)->begin(); }
else if constexpr ( requires { declval<B&>().begin(); } ) {
return ((B*)nullptr)->begin(); }
else if constexpr ( requires { declval<C&>().begin(); } ) {
return ((C*)nullptr)->begin(); }
else
{
static_assert(false, "Wrong types!");
}
}
#include <sstream> // ostringstream
#include <string> // string
#include <vector> // vector
#include <iostream> // cout
int main(void)
{
std::ostringstream ss;
std::string s;
std::vector<int> vec;
typedef decltype(GetType<int>(ss,s,vec)) SomeType;
std::cout << "Hi\n";
}
The above program compiles and runs fine.
>
>
> If the function body is empty then it can typically be a variable template or an alias template.
> Or have no function body at all. You don't need to define it if you're not calling it.
I didn't realise that my previous code would compile and link
successfully without a body, that's cool.
But then there's times when a body is needed, like in the following
function. (Note in places that I had to use *((A*)nullptr) instead of
'declval' because the compiler refused to compile it). You can
dereference a null pointer in a non-evaluated context, it's fine.
#include <type_traits> // is_same, remove_cvref
#include <utility> // declval
template<class ExcludedTypezzz, class Azzz, class Bzzz, class Czzz>
consteval decltype(auto) GetType(Azzz&&, Bzzz&&, Czzz&&) noexcept
{
using std::declval, std::is_same_v, std::remove_cvref_t;
typedef remove_cvref_t<Azzz> A;
typedef remove_cvref_t<Bzzz> B;
typedef remove_cvref_t<Czzz> C;
typedef remove_cvref_t<ExcludedTypezzz> ExcludedType;
constexpr auto is_valid = []<typename ExcludedType2, typename
T>(void) consteval noexcept -> bool
{
if constexpr ( !requires { declval<typename
T::value_type2>(); } ) return false;
else if constexpr ( is_same_v< typename T::value_type2,
void > ) return false;
else if constexpr ( is_same_v< typename T::value_type2,
ExcludedType > ) return false;
else return true;
};
if constexpr ( is_valid.template
operator()<ExcludedType,A>() ) return *(A*)nullptr;
else if constexpr ( is_valid.template
operator()<ExcludedType,B>() ) return *(B*)nullptr;
else if constexpr ( is_valid.template
operator()<ExcludedType,C>() ) return *(C*)nullptr;
else if constexpr ( requires { declval<A&>().begin(); } ) {
return ((A*)nullptr)->begin(); }
else if constexpr ( requires { declval<B&>().begin(); } ) {
return ((B*)nullptr)->begin(); }
else if constexpr ( requires { declval<C&>().begin(); } ) {
return ((C*)nullptr)->begin(); }
else
{
static_assert(false, "Wrong types!");
}
}
#include <sstream> // ostringstream
#include <string> // string
#include <vector> // vector
#include <iostream> // cout
int main(void)
{
std::ostringstream ss;
std::string s;
std::vector<int> vec;
typedef decltype(GetType<int>(ss,s,vec)) SomeType;
std::cout << "Hi\n";
}
The above program compiles and runs fine.
Received on 2025-05-20 12:07:32