6

I want to declare something like this:

template <typename T>
constexpr enable_if_t<is_integral_v<T>, int[]> foo = { 1, 2 };

template <typename T>
constexpr enable_if_t<is_floating_point_v<T>, int[]> foo = { 10, 20, 30 };

But when I try to I'm getting this error:

error: redeclaration of template<class T> constexpr std::enable_if_t<std::is_floating_point<_Tp>::value, int []> foo
note: previous declaration template<class T> constexpr std::enable_if_t<std::is_integral<_Tp>::value, int []> foo<T>

I feel like this should be legal as there will never be more than one foo defined for any given template argument. Is there something I can do to help the compiler understand this?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

1 Answers1

8

Not with overloading.

Your declaration with the enable if is fine, but you cannot have mutiple of them, since variables are not overloadable.

With specialisation, just like with classes, it works just fine:

#include <iostream>
#include <type_traits>

using namespace std;

template <typename T, typename = void>
constexpr int foo[] = {10, 20, 30};

template <typename T>
constexpr int foo<T, enable_if_t<is_integral_v<T>>>[] = { 1, 2 };


int main() {
    cout << foo<int>[0] << endl;
    cout << foo<float>[0] << endl;
}

Since it's not overloading, a single std::enable_if is enough. The enable if is considered more specialized than no specialization, it will be taken as soon as the condition is met, leaving the default case for non integral type template parameter.

Live example

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • Does this code compile? msvc compiler complains, so far ("'std::array': use of class template requires template argument list") – vahancho Jun 14 '19 at 13:03
  • 1
    @vahancho yes it does compile. I added a compiler explorer link. Report a bug if your implementation don't support CTAD – Guillaume Racicot Jun 14 '19 at 13:06
  • @vahancho make sure to compile with C++17 enabled – Fureeish Jun 14 '19 at 13:07
  • @vahancho: You'll need C++17. This code uses deduction guides. [Here](https://wandbox.org/permlink/s8mja7TFV5w8C61n) is a pre-deduction guide compatible version – AndyG Jun 14 '19 at 13:08
  • 1
    @Fureeish Well, then it worth to mention that it doesn't compile with MS compiler(s). For example: https://godbolt.org/z/M53dq1 (-std=c++17 -O3). Am I mistaken? – vahancho Jun 14 '19 at 13:11
  • 1
    @vahancho msvc has different command line argument style: https://godbolt.org/z/Xjai2A (/std:c++17 /O2) – Guillaume Racicot Jun 14 '19 at 13:12
  • @GuillaumeRacicot, ah, ok. Thanks. – vahancho Jun 14 '19 at 13:13
  • I think this isn't working for me because of my array definition. I've tried here: https://ideone.com/fp5TEr How should I be declaring this `int[]`? – Jonathan Mee Jun 14 '19 at 13:28
  • 1
    @JonathanMee I replaced with c-style array syntax. the square brakets are after template angle brakets. – Guillaume Racicot Jun 14 '19 at 13:32
  • 1
    @JonathanMee: You're missing an angle bracket: [Fixed](https://ideone.com/hdy6XS). Guillaume already covered the misplacement of the square brackets. – AndyG Jun 14 '19 at 13:36
  • @AndyG Brilliant, thank you guys for that I'll accept shortly. This is exactly what I'm looking for. – Jonathan Mee Jun 14 '19 at 14:26
  • @AndyG and Guillaume Racicot This worked great for me in my toy example, but when I stepped up to using an array of function pointers it stopped working. I've added a follow up question here: https://stackoverflow.com/q/56649481/2642059 Don't know if you guys would have any follow up insight, but I thought I'd post just in case. – Jonathan Mee Jun 18 '19 at 12:47