Search code examples
c++c++11sfinae

Static member definition of complex type of a template class with SFINAE


It is fairly standard way to declare and define a static const member of a complex type of a template class. However, I would to use SFINAE patter in my class. And that leads to this error: template definition of non-template 'const std::array<unsigned int, 2ul> Message<Self>::kData'. Removing SFINAE resolves the error.

Here is the code:

#include <iostream>
#include <type_traits>
#include <array>

using namespace std;

template <class Self, typename = std::enable_if_t<std::is_class<Self>::value>>
class Message
{
  public:
    bool Verify() const { return static_cast<const Self *>(this)->Verify(); }
    
    static const std::array<uint32_t, 2> kData;
};

class Command : public Message<Command>
{
  public:
    bool Verify() {
        std::cout << "Command::Verify";
        return true;
    }
};

template <class Self, typename = std::enable_if_t<std::is_class<Self>::value>>
const std::array<uint32_t, 2> Message<Self>::kData = { 12, 13 };

int main()
{
    Command cmd;
    cout << "Data: " << cmd.kData[0] << endl;

    return 0;
}

Live code is here. What is the proper syntax to still use SFINAE and properly define the static constant?


Solution

  • What is the proper syntax to still use SFINAE and properly define the static constant?

    Simply using a generic type T

    // ............................V
    template <class Self, typename T>
    const std::array<uint32_t, 2> Message<Self, T>::kData = { 12, 13 };
    // .......................................^^^
    

    Template default types/values aren't used in external definitions.