 // and you can't have a device lambda inside a private member
 // function
 template<typename value_type>
-  struct max_op
-  {
-    __host__ __device__
+struct max_op
+{
+  constexpr static value_type IDENTITY{std::numeric_limits<value_type>::min()};
+
+  __host__ __device__
     value_type operator()(value_type a, value_type b)
     {
       return (a > b? a : b);
     }
-  };
+};
 
 template<typename value_type>
-  struct min_op
-  {
-    __host__ __device__
+struct min_op
+{
+  constexpr static value_type IDENTITY{std::numeric_limits<value_type>::max()};
+
+  __host__ __device__
     value_type operator()(value_type a, value_type b)
     {
       return (a < b? a : b);
     }
-  };
-
+};
 
 // A new instance of this class will be created for each *TEST(GroupByTest, ...)
 // Put all repeated stuff for each test here

  using value_type = typename T::value_type;
  using op_type = typename T::op_type;
  using map_type = concurrent_unordered_map<key_type, value_type, std::numeric_limits<key_type>::max()>;
  using pair_type = thrust::pair<key_type, value_type>;
  using size_type = typename map_type::size_type;

  std::unique_ptr<map_type> the_map;

  const key_type unused_key = std::numeric_limits<key_type>::max();
  const value_type unused_value = std::numeric_limits<value_type>::max();

  size_type size;


// to nest multiple types inside of the KeyValueTypes struct above
// KeyValueTypes<type1, type2> implies key_type = type1, value_type = type2
// This list is the types across which Google Test will run our tests
typedef ::testing::Types< KeyValueTypes<int, int, max_op>,
                          KeyValueTypes<int, float, max_op>,
                          KeyValueTypes<int, double, max_op>,
                          KeyValueTypes<int, long long int, max_op>,
                          KeyValueTypes<int, unsigned long long int, max_op>,
                          KeyValueTypes<unsigned long long int, int, max_op>,
                          KeyValueTypes<unsigned long long int, float, max_op>,
                          KeyValueTypes<unsigned long long int, double, max_op>,
                          KeyValueTypes<unsigned long long int, long long int, max_op>,
                          KeyValueTypes<unsigned long long int, unsigned long long int, max_op>,
                          KeyValueTypes<int, int, min_op>,
                          KeyValueTypes<int, float, min_op>,
                          KeyValueTypes<int, double, min_op>,
                          KeyValueTypes<int, long long int, min_op>,
                          KeyValueTypes<int, unsigned long long int, min_op>,
                          KeyValueTypes<unsigned long long int, int, min_op>,
                          KeyValueTypes<unsigned long long int, float, min_op>,
                          KeyValueTypes<unsigned long long int, double, min_op>,
                          KeyValueTypes<unsigned long long int, long long int, min_op>,
                          KeyValueTypes<unsigned long long int, unsigned long long int, min_op>
                          > Implementations;

TYPED_TEST_CASE(GroupByTest, Implementations);

TYPED_TEST(GroupByTest, AggregationTestHost)
{
  using key_type = typename TypeParam::key_type;
  using value_type = typename TypeParam::value_type;

