This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [libstdc++ PATCH] TR1 'function' and 'mem_fn' support


Paolo Carlini wrote:

Chris Jefferson wrote:

I'm happy to adapt my tuple generation program to generate this header, which would have the advantage it would remove of 10 on the maximum size. Of course this leads to other problems which I'm not positive how to fix.... but it seems like it's not impossible someone might hit the 10-parameter (I've seen functions with more, although not in very nice code)


By the way: *where* is it (the tuple generation program)?!?

Assuming we really we want to go this way, we should provide it and document its usage.

Attached is the most recent version of the maketuples.c program, which generates the header is is currently in the CVS. It could perhaps do with a little more documenting, but I think it's reasonable.

Chris

Paolo.


// 2004-09-23 Chris Jefferson <chris@bubblescope.net>

// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

// This file is designed to generate /include/tr1/tuple. By default it
// generates all length up to 10, although this can be changed by passing
// a command line parameter.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Defines the largest sized tuple which should be created.
int maxsize;

// This defines how far lines should be indented
int indent = 0;

// This defines how far the last drawn line went horizontally
int horizontalpos = 0;

// Records how far along the current line we should start
// This has to be global as we sometimes build up lines in pieces
int offset = 0;

// Prints out n spaces, using tabs as appropriate
void
print_space(int spaces)
{
  int i;
  for(i = 0; i < spaces - 8; i+=8)
    printf("\t");
  for (; i < spaces; i++)
    printf(" ");
}

// Works out strlen when all occurances of %d are replaced
// by a given integer 
int
sub_strlen(char* in, int substitute)
{
  char buffer[200];
  sprintf(buffer, in, substitute, substitute, substitute, substitute);
  return strlen(buffer);
}

/* Checks to see if printing the next line will overflow the line.
 * If so, go onto the next line and move along offset places.
 * Returns 1 if a string of length "length" will fit on existing line
 */
int
check_horizontal(int length, int offset)
{
  int i;
  horizontalpos += length;
  if(horizontalpos > 80)
    {
	printf("\n");
	print_space(offset);
	horizontalpos =  offset + length;
	return 0;
    }
  return 1;
}

char buffer[1000];

/* line takes a line to print, and indents
 * it to the level set by the global 'indent'
 */
void 
line(char* str)
{
  // printf("%d\n", indent);
  if(strlen(str) != 0 )
    {
      print_space(indent);
      printf(str);
    }
  printf("\n");
  horizontalpos = 0;
}

/* loopprint prints as follows:
 * 'start body(0) seperate body(1) ... body(loop-1) end'
 * where body(i) is the string body with up to 3 occurances of %d
 * replaced with i
 * if i=0; then simply 'start end' is outputted
 */ 
void
loopprint_noindent(int loop, char* start, char* body, char *end)
{
  int i = 0;
  printf(start);
  horizontalpos += strlen(start);
  for (i = 0; i < loop-1; i++)
    {
      if(check_horizontal(sub_strlen(body, i) + 2, offset) && i != 0)
	printf(" ");
      printf(body, i, i, i, i, i);
      printf(",");
    }
  if(loop != 0)
    {
      if(check_horizontal(sub_strlen(body, i) + 2 + strlen(end), offset))
	printf(" ");
      printf(body, loop-1, loop-1, loop-1, loop-1, loop-1, loop-1);
    }
  //  check_horizontal(strlen(end)-1, offset);
  printf(end);
  if(strlen(end) != 0 && end[strlen(end)-1] == '\n')
    horizontalpos = 0;
}

void 
loopprint(int loop, char* start, char* body, char *end)
{
  print_space(indent);
  horizontalpos = indent;
  offset = indent;
  if(strcmp(start, ", "))
    offset+=strlen(start);

  loopprint_noindent(loop, start, body, end);
}

/* looplist just takes an integer loop and a char* body, and writes
 * body(0)\n body(1)\n body(2)\n ... body(loop-1)\n
 * where body(i) replaces all occurances of %d with i
 */
void 
looplist(int loop, char* body)
{
  int i;
  for (i = 0; i < loop; i++) 
    {
      print_space(indent);
      printf(body, i, i, i);
      printf("\n");
    }
}

// These are just a bunch of functions that generate commonly used things
void 
braceopen() 
{
  line("{");
  indent += 2;
}

void 
braceclose() 
{
  indent -= 2;
  line("}");
}

void 
classclose() 
{
  indent -= 2;
  line("};");
  line("");
}

//Now the functions that generate the various parts of the header
void
print_preamble()
{
  line("// class template tuple -*- C++ -*-");
  line("");
  line("// Copyright (C) 2004 Free Software Foundation, Inc.");
  line("//");
  line("// This file is part of the GNU ISO C++ Library.  This library is free");
  line("// software; you can redistribute it and/or modify it under the");
  line("// terms of the GNU General Public License as published by the");
  line("// Free Software Foundation; either version 2, or (at your option)");
  line("// any later version.");
  line("");
  line("// This library is distributed in the hope that it will be useful,");
  line("// but WITHOUT ANY WARRANTY; without even the implied warranty of");
  line("// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the");
  line("// GNU General Public License for more details.");
  line("");
  line("// You should have received a copy of the GNU General Public License along");
  line("// with this library; see the file COPYING.  If not, write to the Free");
  line("// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,");
  line("// USA.");
  line("");
  line("/** @file ");
  line(" *  This is a TR1 C++ Library header. ");
  line(" */");
  line("");
  line("// Chris Jefferson <chris@bubblescope.net>");
  line("");
  line("// This header is automatically generated: see maketuple.c for details.");
  line("");
}

void 
reference_wrapper() 
{
  line("// Provides a way to annotate that a reference to");
  line("// an object should be passed.");
  line("template<typename _Tp>");
  indent += 2;
  line("class reference_wrapper");
  braceopen();
  line("_Tp& _M_data;");
  line("public:");
  indent += 2;
  line("typedef _Tp type;");
  line("explicit reference_wrapper(_Tp& __indata): _M_data(__indata)");
  line("{ }");
  line("");
  line("operator _Tp& () const"); 
  braceopen();
  line("return this->get();");
  braceclose();
  line("");
  line("_Tp&");
  line("get() const");
  braceopen();
  line("return _M_data;");
  braceclose();
  indent -= 2;
  classclose();
  indent -= 2;

  line("// Denotes a reference should be taken to a variable.");
  line("template<typename _Tp>");
  indent += 2;
  line("reference_wrapper<_Tp>");
  line("ref(_Tp& __t)");
  braceopen();
  line("return reference_wrapper<_Tp>(__t);");
  braceclose();
  indent -= 2;
  line("");
  line("// Denotes a const reference should be taken to a variable.");
  line("template<typename _Tp>");
  indent += 2;
  line("reference_wrapper<_Tp const>");
  line("cref(const _Tp& __t)");
  braceopen();
  line("return reference_wrapper<_Tp const>(__t);");
  braceclose();
  indent -= 2;
  line("");
}


void 
add_reference() 
{
  line("// Adds a const reference to a non-reference type.");
  line("template<typename _Tp>");
  indent += 2;
  line("struct __add_c_ref");
  line("{ typedef const _Tp& type; };");
  indent -= 2;
  line("");
  line("template<typename _Tp>");
  indent += 2;
  line("struct __add_c_ref<_Tp&>");
  line("{ typedef _Tp& type; };");
  indent -= 2;
  line("");
  line("// Adds a reference to a non-reference type.");
  line("template<typename _Tp>");
  indent += 2;
  line("struct __add_ref");
  line("{ typedef _Tp& type; };");
  indent -= 2;
  line("");
  line("template<typename _Tp>");
  indent += 2;
  line("struct __add_ref<_Tp&>");
  line("{ typedef _Tp& type; };");
  indent -= 2;
  line("");
}

void 
printClass(int in) 
{
  braceopen();
  looplist(in, "_Tp%d _M_t%d;");
  indent -= 2;
  line("");
  line("public:");
  indent += 2;
  // Blank constructor
  line("tuple()");
  line("{ }");
  line("");
  // Explicit constructor
  loopprint(in, "explicit tuple(", 
	    "typename __add_c_ref<_Tp%d>::type __in%d", "):\n");
  indent+=2;
  loopprint(in, "", "_M_t%d(__in%d)", "\n");
  indent-=2;
  line("{ }");
  line("");
  // Copy constructor
  line("tuple(const tuple& __in):");
  indent+=2;
  loopprint(in, "", "_M_t%d(__in._M_t%d)", "\n");
  indent-=2;
  line("{ }");
  line("");
  // Copy from other tuple constructor
 
  loopprint(in, "template<", "typename _Up%d", ">\n");
  indent+=2;
  loopprint(in, "tuple(const tuple<", "_Up%d", ">& __in):\n");
  indent+=2;
  loopprint(in, "", "_M_t%d(__in._M_t%d)", "\n");
  indent-=2;
  line("{ }");
  indent-=2;
  line("");
  // Pair goes here
  if(in == 2)
    {
      line("template<class _Up1, class _Up2>");
      line("  tuple(const std::pair<_Up1, _Up2>& __u):");
      line("     _M_t0(__u.first), _M_t1(__u.second)");
      line("  { }");
      line("");
    }
  // operator = from identical
  line("tuple&");
  line("operator=(const tuple& __in)");
  braceopen();
  looplist(in, "_M_t%d=__in._M_t%d;");
  line("return *this;");
  braceclose();
  line("");
  loopprint(in, "template<", "typename _Up%d", ">\n");
  indent+=2;
  line("tuple&");
  loopprint(in, "operator=(const tuple<", "_Up%d", ">& __in)\n");
  braceopen();
  looplist(in, "_M_t%d=__in._M_t%d;");
  line("return *this;");
  braceclose();
  line("");
  indent-=2;
  line("template<int __i, typename _Up>");
  line("  friend class __get_helper;");
  loopprint(maxsize, "template<", "typename", ">\n");
  line("  friend class tuple;");
  indent-=2; // End of "friend" section
  classclose();
}

void tuple_classes() {
  int i;
  // Do the empty tuple class
  line("// The empty tuple.");
  line("template<>");
  indent += 2;
  loopprint(maxsize, "class tuple<", "_NullClass", ">\n"); 
  line("{");
  line("public:");
  indent += 2;
  // Blank constructor
  line("tuple()");
  line("{ }");
  line("");
  // no explicit constructor
  // Copy constructor
  line("tuple(const tuple& __in)");
  line("{ }");
  line("");
  // no copy from other tuple constructor
  // operator = from identical
  line("tuple& operator=(const tuple& __in)");
  line("{ return *this; }");
  // no operator = from other
  indent -= 2;
  line("};");
  indent -= 2;
  line("");
  // Now do all the other classes
  for (i = 1; i <= maxsize; i++)
    {
      if( i == maxsize)
	line("/// @brief  Template class tuple");
      loopprint(i, "template<", "typename _Tp%d", ">\n");
      indent += 2;
      if(i != maxsize) 
	{
	  loopprint(i, "class tuple<", "_Tp%d", ", ");
	  loopprint_noindent(maxsize-i, "", "_NullClass", ">\n");
	}
      else 
	{
	  line("class tuple");
	}
      printClass(i);
    }
}

void 
tuple_size() {
  int i;
  line("/// Finds the size of a given tuple type.");
  line("template<typename _Tp>");
  line("  struct tuple_size;");
  line("");
  for (i = 0; i <= maxsize; i++)
    {
      if(i == maxsize)
	line("/// @brief  class tuple_size");
      loopprint(i, "template<", "typename _Tp%d", ">\n");
      indent += 2;
      loopprint(i,"struct tuple_size<tuple<", "_Tp%d", "");
      if(i == 0 || i == maxsize)
	loopprint_noindent(maxsize-i, "", "_NullClass", "> >\n");
      else
	loopprint_noindent(maxsize-i, ", ", "_NullClass", "> >\n");
      print_space(indent);
      printf("{ static const int value = %d; };\n", i);
      line("");
      indent-=2;

   }
}

void 
tuple_element()
{
  line("/// Gives the type of the ith element of a given tuple type.");
  int i;
  line("template<int __i, typename _Tp>");
  line("  struct tuple_element;");
  line("");
  for ( i = 0; i < maxsize; i++)
    {
      if(i == maxsize - 1)
	line("/// @brief  class tuple_element");
      loopprint(maxsize, "template<", "typename _Tp%d", ">\n");
      indent += 2;
      sprintf(buffer, "struct tuple_element<%d, tuple<", i);
      loopprint(maxsize, buffer, "_Tp%d", "> >\n");
      print_space(indent);
      printf("{ typedef _Tp%d type; };\n", i);
      indent -= 2;
      line("");
    }
}

void 
tuple_value()
{
  int i;
  line("// Class used in the implementation of get");
  line("template<int __i, typename _Tp>");
  line("  struct __get_helper;\n");
  for (i = 0; i < maxsize; i++) {
    line("template<typename _Tp>");
    indent += 2;
    print_space(indent);
    printf("struct __get_helper<%d, _Tp>\n", i);
    braceopen();
    print_space(indent);
    printf("static typename __add_ref<typename tuple_element<%d, _Tp>::type>::type\n", i);
    line("get_value(_Tp& __in)");
    print_space(indent);
    printf("{ return __in._M_t%d; }\n", i);
    line("");
    print_space(indent);
    printf("static typename __add_c_ref<typename tuple_element<%d, _Tp>::type>::type\n", i);
    line("get_value(const _Tp& __in)");
    print_space(indent);
    printf("{ return __in._M_t%d; }\n", i);
    classclose();
    indent -= 2;
  }
}

void 
get() 
{
  // non-const get
  line("// Returns a reference to the ith element of a tuple.");
  line("// Any const or non-const ref elements are returned with their original type.");
  loopprint(maxsize, "template<int __i, ", "typename _Tp%d", ">\n");
  indent+=2;
  loopprint(maxsize, "typename __add_ref<typename tuple_element<__i, tuple<", "_Tp%d", "> >::type>::type\n");
  loopprint(maxsize, "get(tuple<", "_Tp%d", ">& __t)\n"); 
  braceopen();
  loopprint(maxsize, "return __get_helper<__i, tuple<", "_Tp%d", "> >::get_value(__t);\n");
  braceclose();
  indent-=2;
  line("");
  // const get
  line("// Returns a const reference to the ith element of a tuple.");
  line("// Any const or non-const ref elements are returned with their original type.");
  loopprint(maxsize, "template<int __i, ", "typename _Tp%d", ">\n");
  indent+=2;
  loopprint(maxsize, "typename __add_c_ref<typename tuple_element<__i, tuple<", 
	    "_Tp%d", "> >::type>::type\n");
  loopprint(maxsize, "get(const tuple<", "_Tp%d", ">& __t)\n"); 
  braceopen();
  loopprint(maxsize, "return __get_helper<__i, tuple<", "_Tp%d", "> >::get_value(__t);\n");
  braceclose();
  indent-=2;
  line("");
}

void 
make_compare(char* name, char* before_recurse1, char* before_recurse2, char* after_recurse)
{
  int i;
  print_space(indent);
  printf("static bool __%s(const _Tp& __t, const _Up& __u)\n", name);
  braceopen();
  print_space(indent);
  printf("return %s%s\n", before_recurse1, before_recurse2);
  print_space(indent);
  if(strlen(after_recurse) != 0) {
    print_space(strlen("return ") + strlen(before_recurse1));
  }
  else {
    printf("  ");
  }
  printf(" __tuple_compare<0, __i+1, __j, _Tp, _Up>" 
	 "::__%s(__t, __u)%s;\n", name, after_recurse);
  braceclose();
}

void
end_compare(char* name, int end_val)
{
  print_space(indent);
  printf("static bool __%s(const _Tp&, const _Up&)\n", name);
  if(end_val)
    line("{ return true; }");
  else
    line("{ return false; }");
}

void 
tuple_compare() 
{
  //comparison helper
  line("// This class helps construct the various comparison operations on tuples");
  line("template<int __check_equal_size, int __i, int __j, typename _Tp, typename _Up>");
  line("  struct __tuple_compare;");
  line("");
  line("template<int __i, int __j, typename _Tp, typename _Up>");
  indent+=2;
  line("struct __tuple_compare<0, __i, __j, _Tp, _Up>");
  braceopen();
  make_compare("eq", "get<__i>(__t) == get<__i>(__u) &&", "", "");
  make_compare("less", "(get<__i>(__t) < get<__i>(__u)) ||", " !(get<__i>(__u) < get<__i>(__t)) &&", "");
  classclose();
  indent-=2;
  line("template<int __i, typename _Tp, typename _Up>");
  indent+=2;
  line("struct __tuple_compare<0, __i, __i, _Tp, _Up>");
  braceopen();
  end_compare("eq", 1);
  end_compare("less", 0);
  classclose();
  indent-=2;
}

void 
operator_definition(char* op, char* text_op_name)
{
  // In this function we abuse the various pre-defined formatting commands a bit...
  int i;  
  loopprint(maxsize, "template<", "typename _Tp%d", ", ");
  loopprint_noindent(maxsize, "", "typename _Up%d", ">\n");
  line("bool");
  print_space(indent);
  printf("operator%s(", op);
  horizontalpos = 0;
  loopprint_noindent(maxsize, "const tuple<", "_Tp%d", ">& __t,\n");
  print_space(indent + strlen("operator") + strlen(op) + 1);
  horizontalpos = 0;
  loopprint_noindent(maxsize, "const tuple<", "_Up%d", ">& __u)\n");
  line("{");
  indent += 2;
  loopprint(maxsize, "typedef tuple<", "_Tp%d", "> _Tp;\n");
  loopprint(maxsize, "typedef tuple<", "_Up%d", "> _Up;\n");
  line("return __tuple_compare<tuple_size<_Tp>::value -");
  line(" tuple_size<_Tp>::value, 0,");
  print_space(indent);
printf("  tuple_size<_Tp>::value, _Tp, _Up>::__%s(__t, __u);\n", text_op_name);
  indent -= 2;
  line("}");
  line("");
}

void
secondary_operator_definition(char* op, char* op_text)
{
  loopprint(maxsize, "template<", "typename _Tp%d", ", ");
  loopprint_noindent(maxsize, "", "typename _Up%d", ">\n");
  line("bool");
  print_space(indent);
  printf("operator%s(", op);
  horizontalpos = 0;
  loopprint_noindent(maxsize, "const tuple<", "_Tp%d", ">& __t,\n");
  print_space(indent + strlen("operator") + strlen(op) + 1);
  horizontalpos = 0;
  loopprint_noindent(maxsize, "const tuple<", "_Up%d", ">& __u)\n");
  line("{");
  indent += 2;
  print_space(indent+2);
  printf("return %s;\n",op_text);
  braceclose();
}

void 
strip_reference_wrapper() 
{
  line("// Helper which adds a reference to a type when given a reference_wrapper");
  line("template<typename _Tp>");
  indent+=2;
  line("struct __strip_reference_wrapper");
  braceopen();
  line("  typedef _Tp __type;");
  classclose();
  indent-=2;
  line("template<typename _Tp>");
  indent+=2;
  line("struct __strip_reference_wrapper<reference_wrapper<_Tp> >");
  braceopen();
  line("typedef _Tp& __type;");
  classclose();
  indent-=2;
  line("template<typename _Tp>");
  indent+=2;
  line("struct __strip_reference_wrapper<const reference_wrapper<_Tp> >");
  braceopen();
  line("  typedef _Tp& __type;");
  classclose();
  indent-=2;
  loopprint(maxsize, "template<", "typename _Tp%d = _NullClass", ">\n");
  indent+=2;
  line("struct __stripped_tuple_type");
  braceopen();
  loopprint(maxsize, "typedef tuple<",
	    "typename __strip_reference_wrapper<_Tp%d>::__type", ">");
  line("__type;");
  classclose();
  indent-=2;
}

void
make_tuple()
{
  int i;
  line("tuple<>");
  line("make_tuple()");
  line("{ return tuple<>(); }");
  line("");
  for (i = 1; i <= maxsize; i++) {
    loopprint(i, "template<", "typename _Tp%d", ">\n");
    indent+=2;
    loopprint(i, "typename __stripped_tuple_type<", "_Tp%d", ">::__type\n");
    loopprint(i, "make_tuple(", "_Tp%d __t%d", ")\n");
    braceopen();
    loopprint(i, "return typename  __stripped_tuple_type<", "_Tp%d", ">::\n");
    loopprint(i, "  __type(", "__t%d", ");\n");
    braceclose();
    line("");
    indent-=2;
  }
}

void
make_tie()
{
  int i;
  line("// A class (and instance) which can be used in 'tie' when an element");
  line("// of a tuple is not required");
  line("");
  line("struct swallow_assign");
  braceopen();
  line("template<class T>");
  line("swallow_assign&");
  line("  operator=(const T&)");
  line("  { return *this; }");
  classclose();
  line("// TODO: Put this in some kind of shared file.");
  line("namespace");
  braceopen();
  line("swallow_assign ignore;");
  classclose();
  line("");
  line("// Forms a tuple of references to a list of variables."); 
  for (i = 1; i <= maxsize; i++) {
    loopprint(i, "template<", "typename _Tp%d", ">\n");
    indent+=2;
    loopprint(i, "tuple<", "_Tp%d&", ">\n");
    loopprint(i, "tie(", "_Tp%d& __t%d", ")\n");
    braceopen();
    loopprint(i, "return make_tuple(", "ref(__t%d)", ");\n");
    classclose();
    indent-=2;
  }
}

void
pair_things(void) 
{
  line("// Various functions which give std::pair a tuple-like interface.");
  line("template<class _Tp1, class _Tp2>");
  line("  struct tuple_size<std::pair<_Tp1, _Tp2> >");
  line("  { static const int value = 2; };");
  line("");
  line("template<class _Tp1, class _Tp2>");
  line("  struct tuple_element<0, std::pair<_Tp1, _Tp2> >");
  line("  { typedef _Tp1 type; };");
  line("");
  line("template<class _Tp1, class _Tp2>");
  line("  struct tuple_element<1, std::pair<_Tp1, _Tp2> >");
  line("  { typedef _Tp2 type; };");
  line("");
  line("template<int _I, class _Tp1, class _Tp2>");
  line("  typename tuple_element<_I, tuple<_Tp1, _Tp2> >::type");
  line("  get(pair<_Tp1, _Tp2>& __in)");
  line("  { return get<_I>(tie(__in.first, __in.second)); }");
  line("");
  line("template<int _I, class _Tp1, class _Tp2>");
  line("  typename tuple_element<_I, tuple<_Tp1, _Tp2> >::type");
  line("  get(const pair<_Tp1, _Tp2>& __in)");
  line("  { return get<_I>(tie(__in.first, __in.second)); }");
  line("");
}

int 
main(int argc,char** argv) 
{
  if(argc == 1)
    maxsize = 10;
  else
    {
      maxsize = atoi(argv[1]);
      if(maxsize < 2) 
	maxsize = 2;
    }
  print_preamble();
  line("#ifndef _TUPLE");
  line("#define _TUPLE 1");
  line("");
  line("#include <tr1/utility>");
  line("#include <tr1/functional>");
  line("");
  line("namespace std");
  line("{");
  line("namespace tr1");
  line("{");
  indent+=2;
  // This is just a helper object
  line("// An implementation specific class which is used in the tuple class");
  line("// when the tuple is not maximum possible size.");
  line("struct _NullClass { };");
  line("");
  loopprint(maxsize, "template<", "typename _Tp%d = _NullClass", ">\n");
  indent += 2;
  line("class tuple;");
  indent -= 2;
  line("");
  tuple_element();
  tuple_size();
  add_reference(); //Note: internal class
  tuple_classes();
  tuple_value(); //Note: this is an implemention-specific helper class used in get
  get();
  tuple_compare(); //Note: this is an implemention-specific helper class
  operator_definition("==", "eq");
  operator_definition("<", "less");
  secondary_operator_definition("!=","!(__t == __u)");
  secondary_operator_definition(">","__u < __t");
  secondary_operator_definition("<=","!(__u < __t)");
  secondary_operator_definition(">=","!(__t < __u)");
  line("");
  strip_reference_wrapper(); //Note: this is a helper class for make_tuple
  make_tuple();
  make_tie();
  indent-=2;
  line("}");
  line("}");
  line("");
  line("#endif");
  line("");
  return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]