-1

I have checked out std::enable_if to conditionally compile a member function

However it doesn't work for me. I need to restrict T of a class method to some types.

template<typename T = typename enable_if_t<
    is_same_v<T, long> || is_same_v<T, int> || is_same_v<T, double> 
    || is_same_v<T, float> || is_same_v<T, size_t>>
    >
shared_ptr<Node<T>> LinkedList<T>::AddNumbers(
    shared_ptr<Node<T>> p1, shared_ptr<Node<T>> p2, T carry)
{
    <snip>
}

I get build error:

identifier T is undefined

I am using C++20. Any advice and insight is appreciated.


I try out concepts suggested by @JeJo, but get the following build error on the line performing arithmetics:

error C2676: binary '/': 'T' does not define this operator or 
a conversion to a type acceptable to the predefined operator

I have the template class declaration in header file and implementation in .cpp file. Header file:

template <typename T> class LinkedList
{
public:
    <snip>
    shared_ptr<Node<T>> AddNumbers(
           shared_ptr<Node<T>>, shared_ptr<Node<T>>, T carry = 0);
};

When I use the suggestion by @JeJo, I bump into

error C3855: 'LinkedList<T>': template parameter 'T' is
             incompatible with the declaration
JeJo
  • 30,635
  • 6
  • 49
  • 88
Kok How Teh
  • 3,298
  • 6
  • 47
  • 85

1 Answers1

2

Despite what the other answers say, the member function doesn't need to (and shouldn't) be a template, assuming you use requires. That's only necessary when you use the classical SFINAE.

#include <cstddef>
#include <iostream>
#include <memory>
#include <type_traits>

template <typename T, typename ...P>
concept one_of = (std::is_same_v<T, P> || ...);

template <typename T>
struct Node {};

template <typename T>
class LinkedList
{
public:
    std::shared_ptr<Node<T>> AddNumbers(std::shared_ptr<Node<T>>, std::shared_ptr<Node<T>>, T carry = 0)
    requires one_of<T, int, long, std::size_t, float, double>
    {
        // ...
    }
};

int main()
{
    LinkedList<int> s;
    s.AddNumbers(nullptr, nullptr, 0);

    LinkedList<char> t;
    // t.AddNumbers(nullptr, nullptr, 0);
}

Any boolean condition can be spelled after requires, but I've added a concept for brevity.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • This solution makes more sense. Don't need to instantiate the template methods. – Kok How Teh May 30 '22 at 06:23
  • 2
    The constraint on the member function doesn't make sense to me, which prevents `s.AddNumbers(std::shared_ptr>{}, nullptr, 0)`. If so, why not just constrain the *class* in the first place? IMO the member function *should* be template so that it can accept various arithmetic types. – 康桓瑋 May 30 '22 at 08:02
  • @康桓瑋 I agree, not sure why OP wants that. – HolyBlackCat May 30 '22 at 20:00
  • What do you mean various arithmetic types? The constraints applied to the method is cascaded down to `Node` member field. – Kok How Teh May 31 '22 at 05:19