Search code examples
c++classtemplatesconstructortypename

Defining template function with std::is_invocable_v outside of class


I have this class:

template <typename T>
class Value {
    private:
    bool fixed;
    union {
        T value;
        std::function<T()> get;
    };

    public:
    Value(const T& value);
    template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
    Value(F&& get);
    Value(const T* pointer);
    ~Value();
    operator T();
};

I initially wrote it all on a header file but am now transfering the code to a .cpp file. The problem is I don't know how to include the typename = std::enable_if_t<std::is_invocable_v<F>> part when defining Value(F&& get).

First, I tried:

template <typename T>
template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
Value<T>::Value(F&& get) : fixed(false), get(std::forward<F>(get)) {}

which produced the error:

error: a default template argument cannot be specified on the declaration of a member of a class template outside of its class

Then, after reading this answer, I tried:

template <typename F>
std::enable_if_t<std::is_invocable_v<F>>
Value<T>::Value(F&& get) : fixed(false), get(std::forward<F>(get)) {}

which results in:

error: return type may not be specified on a constructor

What should I do instead?


Solution

  •     template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
        Value(F&& get);
    

    Here, std::enable_if_t<std::is_invocable_v<F>> is a default template argument (default value of the second template argument) and you have already specified it in the declaration inside the class. So, when you add an implementation outside the class, you should omit the default value:

    template <typename T>
    template <typename F, typename>
    Value<T>::Value(F&& get) : fixed(false), get(std::forward<F>(get)) {}
    

    This is indeed what the error says: a default template argument cannot be specified on the declaration of a member of a class template outside of its class