Thread: Problem in template that uses "decltype", "typename", and "std::remove_reference"

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Jul 2014
    Location
    Calgary, Canada
    Posts
    29

    Problem in template that uses "decltype", "typename", and "std::remove_reference"

    Afternoon all,

    I have got a problem here that I cannot get sorted out.

    The attached code runs fine as coded. If, however, you uncomment the alternate return lines 82 and 89 (in UnorderedMap::c0val and UnorderedMap::c1val), compile time errors result.

    This bugs me, because those commented out return lines show the approach I would really prefer to use.

    I have just started learning how to use the new C++11 "decltype" and "std::remove_reference" features in the past few days, so my mistake almost certainly lies at lines 42 to 45, in Sheet::data<I>(), where these are both being used.

    Anyways, here's the code:

    Code:
    #include <tuple>
    #include <unordered_map>
    #include <vector>
    #include <type_traits>
    
    
    #include <cstdio>
    
    
    // Compiler used: gcc version 4.6.3 on Ubuntu, via g++ Typename.C -std=c++0x
    
    
    template<class C0, class C1>
    class Sheet
    {
     public:
    
    
      // Simple "spreadsheet" class with an embedded 2-tuple.
      // Here std::get<0>(embed) is an std::vector<C0>, the "first column",
      //  and std::get<1>(embed) is an std::vector<C1>, the "second column".
    
    
      std::tuple<std::vector<C0>, 
                 std::vector<C1>>   embed;
    
    
      // Template function to return the std::vector::data() pointers of the
      //   C0 and C1 vectors in the embedded object.
      // Since std::get<I>() returns an std::vector<C0 or C1>&, but we want a
      //   (C0*) or (C1*), we need to strip away the reference, and then use
      //   std::vector::value_type to get (C0) or (C1), and add a pointer.
      // I have little experience with "decltype", so this is almost certainly
      //   where the mistake lies.
      // Notice that both std::remove_reference::type and std::vector::value_type
      //   are typenames, but I've got only one "typename" listed here; that
      //   bugs me. (I did try using remove_reference_t, but couldn't figure out
      //   the correct syntax for its use.)
    
    
      template<int I>
      auto data() -> typename std::remove_reference
                              < decltype(std::get<I>(embed))
                              > ::type
                              ::value_type *
      {
        return std::get<I>(embed).data();
      }
    
    
      // Forwarders to the data<I>() template.
      // You'll see in a minute why we need these.
    
    
      C0* c0data() { return data<0>(); }
      C1* c1data() { return data<1>(); }
    };
    
    
    template<class Key, class C0, class C1>
    class UnorderedMap
    {
      // Now, a class with an embedded unordered_map of Keys to Sheet<C0,C1>s.
    
    
     public:
      std::unordered_map<Key, Sheet<C0, C1>> uomap;
    
    
      // These forwarders take a Key argument, and return the data() pointers of
      //   the corresponding Sheet's std::vectors in the embedded unordered_map.
      // PROBLEM pops up at this point:
      // These *only* work when the Sheet::c0data/c1data forwarders are used.
      // Compilation fails if you try to use Sheet::data<I>, with this error:
      // "69:34: error: expected primary-expression before ‘)’ token".
      // Since the only thing Sheet::c0data/c1data do is to call Sheet::data<I>,
      //   I'm at a loss to explain this.
    
    
      C0* c0val(Key key)
      {
      //return uomap.at(key).data<0>(); // Compile time error
        return uomap.at(key).c0data();
      }
    
    
      C1* c1val(Key key)
      {
      //return uomap.at(key).data<1>(); // Compile time error
        return uomap.at(key).c1data();
      }
    };
    
    
    // Test program.
    
    
    int main()
    {
      // Create a simple three-row Sheet<float, double>.
    
    
      Sheet<float,double> s;
      std::get<0>(s.embed) = std::vector<float>  {1., 3., 5.};
      std::get<1>(s.embed) = std::vector<double> {2., 4., 6.};
    
    
      // Print out the addresses of the embedded float and double vectors,
      //   and their first elements (1. and 2.).
    
    
      printf("In original Sheet:\n");
      printf("Vectors are at  %p and %p\n", s.data<0>(),    s.data<1>());
      printf("First values:   %f and %f\n", s.data<0>()[0], s.data<1>()[0]);
    
    
      // Now make up an UnorderedMap whose embedded object contains only one
      //   element: the above-defined Sheet, at integer Key value 3.
    
    
      UnorderedMap<int, float, double> x;
    
    
      x.uomap[3] = s;
    
    
      // Here in main(), there is no problem with using Sheet::data<I>.
    
    
      printf("In UnorderedMap:\n");
      printf("Vectors are at  %p and %p\n", x.uomap[3].data<0>(),    
                                            x.uomap[3].data<1>());
      printf("First  values:  %f and %f\n", x.uomap[3].data<0>()[0], 
                                            x.uomap[3].data<1>()[0]);
      printf("Second values:  %f and %f\n", x.c0val(3)[1],
                                            x.c1val(3)[1]);
    }
    Thanks
    Grump
    Last edited by Grumpulus; 12-08-2014 at 05:12 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can't get "return()" to work.Problem in "if" part
    By coder1 in forum C Programming
    Replies: 13
    Last Post: 09-10-2013, 01:08 AM
  2. Replies: 2
    Last Post: 08-19-2012, 06:15 AM
  3. Replies: 4
    Last Post: 07-17-2012, 09:02 AM
  4. "itoa"-"_itoa" , "inp"-"_inp", Why some functions have "
    By L.O.K. in forum Windows Programming
    Replies: 5
    Last Post: 12-08-2002, 08:25 AM
  5. "CWnd"-"HWnd","CBitmap"-"HBitmap"...., What is mean by "
    By L.O.K. in forum Windows Programming
    Replies: 2
    Last Post: 12-04-2002, 07:59 AM