Demo Use Case For N4027: has_member_function(“MyFunction”)   Project: Programming Language C++ ­ SG7 Reflection  Author: Andrew Tomazos   Date: 9 June 2014 

Demo Use Case For N4027: has_member_function(“MyFunction”)  Objective  Implementation  1. Some Helper Traits and Functions  2. Member Predicate  3. Name Index  4. The Function Itself  Conclusion 

Objective   We show how to build upon the N4027 reflection primitives to define a constexpr function:    template   constexpr bool has_member_function(const char* name);    such that has_member_function(“bar”) will return true iff the class Foo contains a  direct public non­static member function with the name bar.    For example, for the class:    struct MyClass  {  void foo();  int qux;  static void quux();  static int quuux;  void bar();  private:  void priv();  public: 

void baz();  };    The following static assertions will succeed:    static_assert(has_member_function("foo"), "");  static_assert(has_member_function("bar"), "");  static_assert(has_member_function("baz"), "");    static_assert(!has_member_function("nope"), ""); // no such  member  static_assert(!has_member_function("qux"), ""); // qux is  variable  static_assert(!has_member_function("quux"), ""); // quux is  static  static_assert(!has_member_function("quuux"), ""); // quuux  is static variable  static_assert(!has_member_function("priv"), ""); // priv is  private    You can also use has_member_function at run­time:    int main(int argc, char** argv)  {  if (has_member_function(argv[1]))  std::cout << "MyClass has member function " << argv[1] <<  std::endl;  else  std::cout << "MyClass does NOT have member function " <<  argv[1] << std::endl;  };    The index of the member function names is constructed at compile­time as part of the pure  library demo code, it is not provided by a compiler extension.  It consists of a sorted array of the  function names so lookup is O(logN) (either at compile­time if evaluated as part of a constant  expression, or run­time if not)   

Implementation  

1. Some Helper Traits and Functions  

First we add some pure library helper templates.    pointee_type

 gives the pointed to type of a pointer or pointer­to­member.  That is, for P=T* it  gives T, for P=T C::* it gives T.    template struct pointee_type;  template struct pointee_type { using  type = T; }; // for pointer­to­members (non­static members)  template struct pointee_type { using type = T; }; //  for pointers (static members)    is_static

 gives the staticness of a pointer type given by std::class_member_pointer.  If P=T*  the member is static, if P=T C::* the member is non­static:    template bool is_static;  template constexpr bool is_static =  false;  template constexpr bool is_static = true;    Next we add a function to compare string literals (compile­time strings).  It is a constexpr version  of std::strcmp:    constexpr int strlitcmp(const char* a, const char* b)  {       for (size_t i = 0; true; i++)       {           if (a[i] == b[i])           {               if (a[i] == 0)                   return 0;               else                   continue;           }             if (a[i] < b[i]) return ­1; else return +1;       }  }   

2. Member Predicate   We are now ready to define a predicate on which we are going to filter the members of the class.  We are interested in public, non­static, functions.  We simply define the predicate as the 

conjuction of these three properties.  is_pnsmf is true iff the Ith direct member of C is a  public non­static member function:    template  constexpr bool is_pnsmf =      /* public */ std::class_member_access_level_v ==  std::public_access &&      /* non­static */ !is_static::value_type> &&      /* function */ std::is_function::value_type>::type>::value;   

3. Name Index   Now we want to create an index of the names of the members that satisfy the predicate.  First  we need to calculate the storage requirements.  We define a pnsmf_index_dim_t class to hold  the number of strings and the number of total chars we need in the index:    struct pnsmf_index_dims_t  {  size_t nstrings = 0;  size_t nchars = 0;  };    We then make a pass over the members to calculate these requirements.  We use  std::make_index_sequence and calculate the dimensions:    template  constexpr pnsmf_index_dims_t  get_pnsmf_index_dims(std::index_sequence)  {      size_t nstrings = 0, nchars = 0;        for (bool b : { is_pnsmf... })          nstrings += b;        for (size_t x : { (is_pnsmf ?  std::class_member_name::size + 1 : 0)... } )  nchars += x;        return {nstrings, nchars}; 

}    We then assign the dimensions to a static constexpr pnsmf_index_dims variable template:    template constexpr auto pnsmf_index_dims       =  get_pnsmf_index_dims(std::make_index_sequence>());    Now that we know our space requirements statically we can go ahead and define our index data  structure pnsmf_index_t.  It holds an array of the character data for the strings, and an array of  offsets within that array where each string starts.  The offsets will be sorted in lexigraphical order  so the index can be binary searched.  We will mention you can use a hash table instead here,  but to keep the demo simple we just use a sorted array.    template   struct pnsmf_index_t  {  static constexpr size_t nstrings = nstrings_in;  static constexpr size_t nchars = nchars_in;  size_t stroff[nstrings] = {0};  char chardata[nchars] = {0};  };    Now we define a function that builds the index for each class.  We make another pass over the  members and store those that satisfy the predicate in our index.  We then sort the index.  For  sorting we have used O(n^2) bubblesort for simplicity, but you can easily imagine how to use  mergesort or quicksort here with just a few more lines of code:    template  constexpr pnsmf_index_t.nstrings,  pnsmf_index_dims.nchars>  get_pnsmf_index(std::index_sequence)  {  constexpr auto dims = pnsmf_index_dims;    pnsmf_index_t ret;    size_t current_stroff = 0;  size_t current_chardata = 0;    for (const char* s : { (is_pnsmf ?  std::class_member_name_v : nullptr)... } ) 

if (s)  {  ret.stroff[current_stroff++] = current_chardata;  for (const char* p = s; true; p++)  {  ret.chardata[current_chardata++] = *p;  if (!*p)  break;  }  }    bool ok = true;  do  {  ok = true;  for (size_t i = 0; i+1 < dims.nstrings; i++)  if (strlitcmp(ret.chardata +  ret.stroff[i],ret.chardata + ret.stroff[i+1]) >= 0)  {  size_t t = ret.stroff[i];  ret.stroff[i] = ret.stroff[i+1];  ret.stroff[i+1] = t;  ok = false;  }  }  while (!ok);    return ret;  };    Then we create a static constexpr variable template pnsmf_index that is initialized with the  built index for each class on instantiation:    template constexpr auto pnsmf_index       =  get_pnsmf_index(std::make_index_sequence>());   

4. The Function Itself   Now that we have built the index, we can define the has_member_function function that  performs a binary search of it: 

  template   constexpr bool has_member_function(const char* name)  {  constexpr auto& idx = pnsmf_index;    size_t a = 0, b = idx.nstrings;    while (a != b)  {  size_t c = a + (b­a) / 2;  switch (strlitcmp(name, idx.chardata + idx.stroff[c]))  {  case 0: return true;  case ­1:  b = c;  break;  case +1:  a = c+1;  break;  }  }    return false;  }    and we’re done. 

Conclusion   We should note that this use case is not a primary one for N4027 or for reflection in general.  Also, we want to make clear that this is just a demo, for production purposes we anticipate  production quality non­standard reflection libraries will be built atop N4027 that have more  sophistication than the quick direct demo indexing we have shown here.  Our purpose for this  demo is to prove that all the necessary information is exposed by our minimal compile­supported  traits, and that it is possible to use it efficiently from pure library code.    The code in this paper has been tested, and the code under Goal works as shown verbatim.   

Demo Use Case For N4027: has_member_function ... -

First we add some pure library helper templates. ... We are now ready to define a predicate on which we are going to filter the members of the class.

182KB Sizes 1 Downloads 109 Views

Recommend Documents

Use Case Jump - GitHub
Erstellen des UCDokuments. Ruth W. 02/11/2015. 1.1. Mockup und Activity Diagram eingefügt. Ruth W., Kassandra F. 06/04/2016. 1.2. Allgemeine Änderungen.

Southeast Asia Use Case
To start working with GPlates load the files from your Data Bundle for. Beginners: - Click on the .... can download these images from the Earthbyte website ... importing Rasters databundle also contains the MITP08 model, so feel free to try it out ..

Use-Case-School.pdf
Page 2 of 6. Altlimit (Alternative to Limitations). Chip'n Ship for Schools. 1. A Crowdfunding Platform for Online Shopping & Group Gifting. Chip'n Ship is a new ...

The Medical Use of Marijuana.The Case for Clinical Trials_Journal of ...
Page 3 of 10. The Medical Use of Marijuana.The Case for Clinical T ... uest Editorials_Richard Doblin_Mark Kleiman_1995.pdf. The Medical Use of Marijuana.

use case diagram for airline reservation system pdf
There was a problem previewing this document. Retrying... Download. Connect more apps... Try one of the apps below to open or edit this item. use case ...

Fraud, Waste, and Abuse Use Case - GitHub
amounted to $870,000 in fraudulent expenses being filed between August 2007 and. September 2009 https://www.irs.gov/pub/foia/ig/ci/LAFO-2013-11.pdf ... implies an overnight stay or toll based upon ESRI routing). • Likelihood estimates of treatment

Delaunay Triangulation Demo - GitHub
by Liu jiaqi & Qiao Xin & Wang Pengshuai. 1 Introduction. Delaunay triangulation for a set P of points in a plane is a triangulation DT(P) such that no point in P is ...

Demo CIC.pdf
There was a problem previewing this document. Retrying... Download. Connect more apps... Try one of the apps below to open or edit this item. Main menu.

Workflow Demo for Ribo-Seq and polyRibo-Seq - GitHub
Jun 22, 2016 - most important difference among the two is that polyRibo-Seq utilizes polyribosomal .... results are written to a PDF file named fastqReport.png.

Demo: Terra – Scripting customized components for Wireless ... - EWSN
Demo: Terra – Scripting Customized Components for Wireless ... the application script. In this work ... programmer to build a reasonably powerful application in a.

Directions For Use - GitHub
Page 7 of 46. 4. Using EMPOP to perform mtDNA haplotype frequency estimates. EMPOP follows the revised and extended guidelines for mitochondrial DNA typing issued by the DNA commission of the ISFG (Parson et al. 2014). See document for further detail

Leadcrunch - Logistics Use Case v5.pdf
There was a problem previewing this document. Retrying... Download. Connect more apps... Try one of the apps below to open or edit this item. Leadcrunch ...

JAIIB- ACCOUNTS-DEMO STUDY MATERIAL.pdf
What is Accounting? Accounting, as an information system is the process of identifying, measuring and. communicating the financial information of an ...

Demo: Ball and Plate Wireless Control - EWSN
now targeting control applications in many domains such as industries ... monitoring systems. Despite ... antee, at the application level, the state of the system.

Use Case Modeling Guidelines 1. Abstract 2 ...
technique for performing software requirements analysis and specification. ..... The user chooses an account type from a pull-down menu bar on the GUI.

Math Stacks Math Stacks Use Case Diagram
Create a set of Problems. Practice. Problems. Randomly generated. Quizzes. Teacher made Quizzes. View Personal. Scores. View Student. Scores. Create an. Account. Teacher. Student. >. Math Stacks. Math Stacks Use. Case Diagram.