What is wrong with using std :: enable_if?

I have a function set_datathat I have to implement differently for the different types in which it accepts. For example, this is an attempt to implement two overloads based on the input type. If this is fundamental, neither voidand not nullptr_t, then process it in the first implementation. If it is a buffer std::stringor char, process it in the second way.

struct field
{
    template<typename TDataType, typename=void>
    void set_data(TDataType data, size_t index = 0);
};

template<typename TDataType, typename = typename
        std::enable_if< std::is_fundamental<TDataType>::value &&
                        std::is_same<TDataType, nullptr_t>::value == false &&
                        std::is_same<TDataType, void>::value == false>::type>
void field::set_data(TDataType data, size_t index /* = 0 */)
{
}

template<typename TDataType, typename = typename
        std::enable_if< std::is_same<std::string const &, TDataType> ||
                        std::is_same<char const *, TDataType>>::type>
void field::set_data(TDataType data, size_t index /* = 0 */)
{
}

Then I call:

field f;
int x = 10;
f.set_data(x);

And the compiler gives me an error.

defs.h(111): error C2995: 'void messaging::field::set_data(TDataType,size_t)' : function template has already been defined

How to resolve this?

At visual studio 2013

+4
source share
3 answers

SFINAE , , , , 100%, ( EDIT: Agnew , , ). std::enable_if , ( gcc clang):

struct field
{
    template<typename TDataType>
    void set_data(TDataType data, size_t index = 0) {}

    template<typename TDataType>
    typename std::enable_if<std::is_fundamental<TDataType>::value &&
                            !std::is_same<TDataType, std::nullptr_t>::value &&
                            !std::is_same<TDataType, void>::value,
                            void>::type
    set_data(TDataType data, size_t index /* = 0 */)
    {
    }

    template<typename TDataType>
    typename std::enable_if<std::is_same<std::string const &, TDataType>::value ||
                            std::is_same<char const *, TDataType>::value,
                            void>::type
    set_data(TDataType data, size_t index /* = 0 */)
    {
    }

};

( , , value std::is_same int std::nullptr_t).

+2

, , , . , , -, .

. . , ( ::value ):

struct field
{
    template<typename TDataType, typename = typename
            std::enable_if< std::is_fundamental<TDataType>::value &&
                            std::is_same<TDataType, std::nullptr_t>::value == false &&
                            std::is_same<TDataType, void>::value == false>::type>
    void set_data(TDataType data, size_t index = 0)
    {
    }

    template<typename TDataType, typename = void, typename = typename
            std::enable_if< std::is_same<std::string const &, TDataType>::value ||
                            std::is_same<char const *, TDataType>::value>::type>
    void set_data(TDataType data, size_t index = 0)
    {
    }
};

, , pass-by-value, . , is_same<std::string const &, TDataType> , std::string const & . , std::string. std::remove_reference std::remove_cv, .

+4

enable_if SFINAE on (member) ( ) ( ).

struct field
{
    template<typename TDataType>
    typename std::enable_if< std::is_fundamental<TDataType>::value &&
                            !std::is_same<TDataType, std::nullptr_t>::value &&
                            !std::is_same<TDataType, void>::value>::
    type field::set_data(TDataType data, size_t index = 0)
    {
    }

    template<typename TDataType>
    typename std::enable_if< std::is_same<std::string const&, TDataType>::value ||
                             std::is_same<char const*, TDataType>::value>::
    type field::set_data(TDataType data, size_t index = 0)
    {
    }
};
+3
source

All Articles