Search code examples
c++templatestype-traits

How to initialise and return an std::array within a template function?


I'd like a template function that returns some initialisation.

I did the following:

#include<iostream>
#include<array>

template <typename T>
inline static constexpr T  SetValues()
{
    if(std::is_integral<T>::value)
    {
      std::cout<<"int\n";
      return T{1};
    }
    else
    {
      std::cout<<"array\n";
      T arr = {1,2,3,4};
      return arr;
    }
}


int main()
{
 int a = 6;
 std::array<int, 4> arr = {2,2,2,2};
 a = SetValues<decltype(a)>();
 arr = SetValues<decltype(arr)>();
 return 0;
}

which correctly initialises the int but in case of the array I get the error

scalar object ‘arr’ requires one element in initializer

How should I initialise and return the array?


Solution

  • The problem is that, when T = int, you're trying to trying to initialize int arr with initializer list {1, 2, 3, 4} in the else branch. Even if you don't execute the else branch, the compiler still has to compile it and int arr = {1, 2, 3, 4} is invalid syntax.

    On C++17 (and higher), you can get away with if constexpr:

    template <typename T>
    inline static constexpr T SetValues() {
        if constexpr (std::is_integral<T>::value) {
            std::cout << "int\n";
            return T{1};
        } else {
            std::cout << "array\n";
            T arr = {1, 2, 3, 4};
            return arr;
        }
    }
    

    With if constexpr, the compiler won't compile the else branch when T is an integral type (e.g. int) and will not compile the if branch when T is not an integral type.