For the behavior you need, enable_if should be used in conjunction with type inference. If you need a minimum of changes, you can do this:
template<typename U = T> std::size_t setValueToBuffer(std::vector<char>& buffer, std::size_t alignment, typename std::enable_if<std::is_arithmetic<U>::value, std::size_t>::type* = nullptr) const noexcept { static_assert(std::is_same<T, U>::value, "wrong types"); //... } template<typename U = T> std::size_t setValueToBuffer(std::vector<char>& buffer, std::size_t alignment, typename std::enable_if<std::is_same<U, std::string>::value, std::string>::type* = nullptr) const noexcept { static_assert(std::is_same<T, U>::value, "wrong types"); //... }
UPD 01:
It may be worthwhile to render the setValueToBuffer functionality into a separate structure template and specialize it for the necessary types.
namespace details { template<typename T> struct SetValueToBufferAux;//Общий шаблон не определяется }//end of namespace details template<typename T, typename = typename std::enable_if< std::is_arithmetic<T>::value || std::is_same<T, std::string>::value>::type> class NBTTag { //Вам точно нужен enable_if в параметрах шаблона класса? //Если нет, то можно поменять на static_assert: //static_assert(std::is_arithmetic<T>::value || std::is_same<T, std::string>::value, "wrong type"); public: //... std::size_t setValueToBuffer(std::vector<char>& buffer, std::size_t alignment) const noexcept { return details::SetValueToBufferAux<T>()(*this, buffer, alignment);//Просто делегируем вызов } private: friend class details::SetValueToBufferAux<T>;//Если SetValueToBufferAux должен иметь доступ к приватным членам }; //Специализации SetValueToBufferAux для нужных типов namespace details { template<> struct SetValueToBufferAux<int> { std::size_t operator() (NBTTag<int> const & tag, std::vector<char>& buffer, std::size_t alignment) const noexcept { //... return 0; } }; template<> struct SetValueToBufferAux<std::string> { std::size_t operator() (NBTTag<std::string> const & tag, std::vector<char>& buffer, std::size_t alignment) const noexcept { //... return 0; } }; //Если нужно добавить другой тип, то просто пишем нужную специализацию. }//end of namespace details
UPD 02:
The code above will force you to write specializations for EVERY type used, for example, for EVERY arithmetic type you will need to provide a specialization SetValueToBufferAux . I consider this unacceptable for this case. You can modify SetValueToBufferAux as follows:
namespace details { //Добавляем дополнительный параметр заданный по-умолчанию template<typename T, typename = void> struct SetValueToBufferAux; }//end of namespace details //Класс NBTTag остается неизменным namespace details { //Специализация для арифметических типов template<typename T> struct SetValueToBufferAux<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> { std::size_t operator() (NBTTag<T> const & tag, std::vector<char>& buffer, std::size_t alignment) const noexcept { //... } }; //Специализация для отдельного типа template<> struct SetValueToBufferAux<std::string> { std::size_t operator() (NBTTag<std::string> const & tag, std::vector<char>& buffer, std::size_t alignment) const noexcept { //... } }; }//end of namespace details