Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template metaprogramming to match function signature exactly

With template meta-programming it's possible to query properties of types. For example in the case below I'm checking if a certain type has a member function "foo" which takes in another type as the argument.

Is there a way to check if the parameter type is an exact match for the template vs. one that be converted to it, e.g. double or char can be converted into float (causing main to print true twice) but I'm trying to see if there is a way to structure my_test_t so that it matches perfectly, i.e. main() prints false unless T2 = float.

struct S2
{
   int foo(float x)
   {
      return 0;
   }
};

template <typename T1, typename T2>
using my_test_t = decltype(declval<T1>().foo(declval<T2>()));

template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{
};

template <typename T1, typename T2>
struct is_formed<T1, T2, void_t<my_test_t<T1, T2>>> : std::true_type
{
};


int main()
{
   cout << boolalpha << is_formed<S2, double>::value << endl;
   cout << boolalpha << is_formed<S2, char>::value << endl;
}
like image 882
user3882729 Avatar asked Mar 11 '26 09:03

user3882729


2 Answers

You were almost there. I changed the test so that I take the address of foo and test the type of the resulting pointer-to-member by static_casting it to itself.

#include <type_traits>
#include <iostream>
using namespace std;

struct S2
{
   int foo(float x)
   {
      return 0;
   }
};

template <typename T1, typename T2>
using my_test_t = decltype( static_cast<int(T1::*)(T2)>(&T1::foo) );

template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{ };

template <typename T1, typename T2>
struct is_formed<T1, T2, void_t< my_test_t<T1,T2> >> : std::true_type
{ };

int main()
{
   cout << boolalpha << is_formed<S2, float>::value << endl;  // true
   cout << boolalpha << is_formed<S2, double>::value << endl; // false
   cout << boolalpha << is_formed<S2, char>::value << endl;   // false
}

(The code above compiles with C++17 because there's no std::void_t in C++14 - you need to write your own.)

like image 193
jrok Avatar answered Mar 13 '26 10:03

jrok


You can try to use std::is_same to match exact types for foos arguments, for a start you would have to define a type in the struct to compare with.

There could be a better way, I wouldnt know off hand.

like image 32
Moshe Rabaev Avatar answered Mar 13 '26 10:03

Moshe Rabaev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!