can I use SFINAE to selectively define a member va

2019-03-19 11:19发布

问题:

So what I want to do is to create a template class which may or may not contain a member variable based on the template argument passed in. like following:

template<typename T, bool flag>
class base
{
   foov<std::enable_if<flag, T>::type> m_var;
};

the above code could not survive the compiler.

Does anyone know how I can achieve this?

回答1:

Have a base class with enabled/disabled members based on template parameters:

template<typename T, typename Enable = void>
class base_class;

// my favourite type :D
template<typename T>
class base_class<T, std::enable_if_t<std::is_same<T, myFavouriteType>::value>>{
    public:
        int some_variable;
};

// not my favourite type :(
template<typename T>
class base_class<T, std::enable_if_t<!std::is_same<T, myFavouriteType>::value>>{
    public:
        // no variable
};

template<typename T>
class derived_class: public base_class<T>{
    public:
        // do stuff
};

This should give you a nice way to enable/disable members based on type.



回答2:

I think this is what you are looking for.

The class template does not have any member data by default.

template<typename T, bool flag>
class base
{
};

Add a specialization of the class template that has the member data.

template<typename T>
class base<T, true>
{
   foov<T> m_var;
};


回答3:

#pragma once
#include <type_traits>

template <typename T, bool D, typename Enabled=void>
class Node;


template <typename T, bool D>
class Node<T, D, std::enable_if_t<D>>
{
public:
    Node(const T& v) : value(v) {}

private:
    T value;
    Node* next = nullptr;
};

template <typename T, bool D>
class Node<T, D, std::enable_if_t<!D>>
{
public:
    Node(const T& v) : value(v) {}

private:
    T value;
    Node* next = nullptr;
    Node* prev = nullptr;
};

Single or double linked list node based on boolean flag



回答4:

I have a workaround for this. Probably looks ugly but does resolve some of my issues

First I define a type with zero size:

typedef int zero[0];

Next I create a macro:

#ifndef VAR

#define VAR(Enable,YourType,VarName) \    

std::conditional< Enable,YourType,zero >::type VarName

#endif

Then a class like this:

template < int Cond >
class Foo
{
    VAR(Cond == 0,int,var);

    void print()
    {
        if (!sizeof(var)) return;
        //...
    }
};

When you are using a result like var, check the size of it before using it. If the size is zero, it is invalid.



标签: c++ sfinae