how can I write this C++17 in c++14?

I have this code that compiles perfectly in C++17:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <type_traits>



template<typename T, typename ...>
struct first_arg
{
	using type = T;
};

template<typename ...Args>
using first_arg_t = typename first_arg<Args...>::type;

template<typename T, typename U>
constexpr bool is_same_v = std::is_same<T, U>::value;

// line 19
template<typename T, typename...Args>
constexpr bool are_same_v = std::conjunction<is_same_v<T, Args>...>::value;

// using C++17
template<typename...Args>
std::enable_if_t<are_same_v<Args...>, first_arg_t<Args...>>
add( const Args&...args) noexcept
{
	return (args + ...);
}


I tried writing it in C++ 14:

1
2
3
4
5
6
7
8
9
10
11
12
13
// using C++14
template<typename T>
T add14(const T& t)
{
	return t;
}

template<typename T, typename...Tail>
std::enable_if<are_same_v<T,Tail...>, first_arg_t<T,Tail...>>::type
add14( const T& t, const Tail& ... tail)
{
	return t + add14(tail...);
}


i get errors:


'_Traits': parameter pack expects a type template argument   // line 19
constexpr bool are_same_v = std::conjunction<is_same_v<T, Args>...>::value; // line 19


Can someone spot the problem?


I call this with this code:

1
2
3
4
void useAdd()
{
	auto x = add14(5, 20, 35, 10);
}


Last edited on
First problem is that std::conjunction is not part of C++14.
Second problem is the missing typename in front of std::enable_if in the return type. You could also use std::enable_if_t.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <type_traits>
#include <iostream>

template <typename T, typename...> 
  struct all_same_type; 
template <typename T> 
  struct all_same_type<T> 
  {
    static constexpr bool value = true; 
  };
template <typename T, typename U, typename... Us> 
  struct all_same_type<T, U, Us...>
  {
    static constexpr bool value = 
      std::is_same<T, U>::value && all_same_type<T, Us...>::value;
  };

template <typename T> constexpr T add14(T const& x) { return x; }
template <typename T, typename... Ts, 
    typename = std::enable_if_t<all_same_type<T, Ts...>::value>>
  constexpr T add14(T const& x, Ts const&... xs) { return x + add14(xs...); }
  
int main()
{
  std::cout << add14(1, 2, 3, 4, 5) << '\n';
}


Note that add14 is more restrictive on the types of its arguments than built-in operator+.

A potential alternative could be
1
2
3
4
5
template <typename T> 
  T add11(std::initializer_list<T> xs)
  { 
    return std::accumulate(xs.begin(), xs.end(), T{}); 
  }
Last edited on
Topic archived. No new replies allowed.