  * @Returns On failure, returns appropriate error code. Otherwise, GDF_SUCCESS
  */
 /* ----------------------------------------------------------------------------*/
-template <typename groupby_type, typename aggregation_type, template <typename T> class op>
-gdf_error dispatched_groupby(int ncols,               
-                             gdf_column* in_groupby_columns[],        
-                             gdf_column* in_aggregation_column,       
-                             gdf_column* out_groupby_columns[],
-                             gdf_column* out_aggregation_column,
-                             bool sort_result = false)
-{
-
+template <typename aggregation_type, 
+          template <typename T> class op,
+          typename size_type>
+gdf_error typed_groupby(gdf_table<size_type> const & groupby_input_table,
+                        gdf_column* in_aggregation_column,       
+                        gdf_table<size_type> & groupby_output_table,
+                        gdf_column* out_aggregation_column,
+                        bool sort_result = false)
+{
   // Template the functor on the type of the aggregation column
   using op_type = op<aggregation_type>;
 
   // Cast the void* data to the appropriate type
-  groupby_type * in_group_col = static_cast<groupby_type *>(in_groupby_columns[0]->data);
   aggregation_type * in_agg_col = static_cast<aggregation_type *>(in_aggregation_column->data);
-  groupby_type * out_group_col = static_cast<groupby_type *>(out_groupby_columns[0]->data);
-
   // TODO Need to allow for the aggregation output type to be different from the aggregation input type
   aggregation_type * out_agg_col = static_cast<aggregation_type *>(out_aggregation_column->data);
 
-  const gdf_size_type in_size = in_groupby_columns[0]->size;
-  gdf_size_type out_size{0};
-
-  if(cudaSuccess != GroupbyHash(in_group_col, in_agg_col, in_size, 
-                                out_group_col, out_agg_col, &out_size, op_type(), sort_result))
+  size_type output_size{0};
+
+  if(cudaSuccess != GroupbyHash(groupby_input_table, 
+                                in_agg_col, 
+                                groupby_output_table, 
+                                out_agg_col, 
+                                &output_size, 
+                                op_type(), 
+                                sort_result))
   {
     return GDF_CUDA_ERROR;
   }
 
   // Update the size of the result
-  out_groupby_columns[0]->size = out_size;
-  out_aggregation_column->size = out_size;
+  groupby_output_table.set_column_length(output_size);
+  out_aggregation_column->size = output_size;
 
   return GDF_SUCCESS;
 }

  // FIXME When the aggregation type is COUNT, use the type of the OUTPUT column
  // as the type of the aggregation column. This is required as there is a limitation 
  // hash based groupby implementation where it's assumed the aggregation input column
  if(is_same_functor<count_op, op>::value)
  {
    aggregation_column_type = out_aggregation_column->dtype;

  {
    case GDF_INT8:   
      { 
        return typed_groupby<int8_t, op>(groupby_input_table, 
                                         in_aggregation_column, 
                                         groupby_output_table, 
                                         out_aggregation_column, 
                                         sort_result);
      }
    case GDF_INT16:  
      { 
        return typed_groupby<int16_t, op>(groupby_input_table, 
                                          in_aggregation_column, 
                                          groupby_output_table, 
                                          out_aggregation_column, 
                                          sort_result);
      }
    case GDF_INT32:  
      { 
        return typed_groupby<int32_t, op>(groupby_input_table, 
                                          in_aggregation_column, 
                                          groupby_output_table, 
                                          out_aggregation_column, 
                                          sort_result);
      }
    case GDF_INT64:  
      { 
        return typed_groupby<int64_t, op>(groupby_input_table, 
                                          in_aggregation_column, 
                                          groupby_output_table, 
                                          out_aggregation_column, 
                                          sort_result);
      }
    case GDF_FLOAT32:
      { 
        return typed_groupby<float, op>(groupby_input_table, 
                                        in_aggregation_column, 
                                        groupby_output_table, 
                                        out_aggregation_column, 
                                        sort_result);
      }
    case GDF_FLOAT64:
      { 
        return typed_groupby<double, op>(groupby_input_table, 
                                         in_aggregation_column, 
                                         groupby_output_table, 
                                         out_aggregation_column, 
                                         sort_result);
      }
    case GDF_DATE32:    
      {
        return typed_groupby<int32_t, op>(groupby_input_table, 
                                          in_aggregation_column, 
                                          groupby_output_table, 
                                          out_aggregation_column, 
                                          sort_result);
      }
    case GDF_DATE64:   
      {
        return typed_groupby<int64_t, op>(groupby_input_table, 
                                          in_aggregation_column, 
                                          groupby_output_table, 
                                          out_aggregation_column, 
                                          sort_result);
      }
    case GDF_TIMESTAMP:
      {
        return typed_groupby<int64_t, op>(groupby_input_table, 
                                          in_aggregation_column, 
                                          groupby_output_table, 
                                          out_aggregation_column, 
                                          sort_result);
      }
    default:
      std::cerr << "Unsupported aggregation column type: " << aggregation_column_type << std::endl;
      return GDF_UNSUPPORTED_DTYPE;
  }
}


/* --------------------------------------------------------------------------*/
/** 
