Joachim
Joachim

Reputation: 749

enable_if method specialization with implementation outside of class declaration

I'm writing a templated singleton superclass, that can provide a thread-local instance or a process-global instance. The code below compiles and technically fits my need. But, how can I write the function implementation outside of the class declaration? How do I declare the function in the class (is the commented line right)?

All similar questions implement the function in the class declaration.

#include <vector>
#include <type_traits>


using namespace std;

template <class t, bool tls=true>
class A{
public:
  typedef std::vector<t> Avector;
//  static Avector& getVector();

  template <class T=t, bool TLS=tls, typename std::enable_if<!TLS>::type* = nullptr>
  static Avector&
  getVector(){
    static Avector v=Avector();
    return v;
  }

  template <class T=t, bool TLS=tls, typename std::enable_if<TLS>::type* = nullptr>
  static Avector&
  getVector(){
    static thread_local Avector v=Avector();
    return v;
  }
};

int main(){
  vector<int>& vi = A<int>::getVector();
  vector<double>& vd = A<double, false>::getVector();
  return 0;
}

Upvotes: 2

Views: 406

Answers (2)

NoxFly
NoxFly

Reputation: 198

I was searching an answer, and we got one on Stack Overflow 2 years after you posted your question, here : How to use std::enable_if on method of templated class with seperate declaration and definition via specialization.

  1. First, you have to redefine the method as a template, with another typename, and with default value the class's template.
  2. Second, you have to template<> 2 times on the implementation's side.
// hpp
template<typename T>
class A {
    template <class U=T, typename std::enable_if_t<myCondition, bool>>
    void myMethod();
}
// cpp
template<typename T>
template <class U=T, typename std::enable_if_t<myCondition, bool>>
void A::myMethod() {
    // ...
}

If you don't want to define another template parameter, you can define the restriction as return type. Here we changed bool by void, but it can be whatever you want :

// hpp
template<typename T>
class A {
    typename std::enable_if_t<myCondition, void>
    myMethod();
}
// cpp
template<typename T>
typename std::enable_if_t<myCondition, void>
A::myMethod() {
    // ...
}

Upvotes: 0

Passer By
Passer By

Reputation: 21131

You can instead write

template<typename T, bool>
struct A
{
    typedef std::vector<T> Avector;
    static Avector& getVector();
};

template<typename T, bool b>
typename A<T, b>::Avector& A<T, b>::getVector()
{
    thread_local typename A<T, true>::Avector v;
    return v;
}

template<typename T>
class A<T, false>
{
    typedef std::vector<T> Avector;
    static Avector& getVector();
};

template<typename T>
typename A<T, false>::Avector&  A<T, false>::getVector()
{
    static typename A<T, false>::Avector v;
    return v;
}

Also, generally singletons shouldn't be used

Upvotes: 2

Related Questions