• Create Account

### #Actualsundersoft

Posted 01 September 2012 - 05:36 PM

You could try changing the specialization to:

template <> typename std::enable_if<std::is_arithmetic<mytype>::value, mytype>::type func(const mytype& x) noexcept;


I could try this but it would involve specializing is_arithmetic for mytype which is something I don't really want to do. Even still it would only evaluate to true and produce the same problems.

I really doubt you're going to be able to specialize the function if your type doesn't have is_arithmetic<mytype>::value==true . You are allowed to specialize templates in the standard library (under certain conditions). The following code compiles even though the mytype specialization of func doesn't use is_arithmetic:

#include <iostream>
#include <type_traits>
// firstsomething.hpp
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type func(const T& x) noexcept
{ return x; }
// something.hpp
class mytype {
};
namespace std {
template<> class is_arithmetic<mytype> {
static const bool value=1;
};
}
template <> mytype func(const mytype& x) noexcept { return mytype(); }
int main() {
func(0.0);
func(0);
}


If the is_arithmetic specialization was removed, the code would fail to compile on GCC 4.6. If your type is not an arithmetic type then I think you're going to have to use function overloading.

I think I was concerned that creating an overload would break func for integer types because mytype does not have an explicit constructor and it still takes a single argument integer value. However this is not the case apparently.

Yes; the compiler will prefer to instantiate a template over having a cast and using a non-template (although you can force it to use the non-template version by generating a function pointer to it and calling it, or you can force it to use a template by specifying the template arguments explicitly).

### #1sundersoft

Posted 01 September 2012 - 05:36 PM

You could try changing the specialization to:

template <> typename std::enable_if<std::is_arithmetic<mytype>::value, mytype>::type func(const mytype& x) noexcept;


I could try this but it would involve specializing is_arithmetic for mytype which is something I don't really want to do. Even still it would only evaluate to true and produce the same problems.

I really doubt you're going to be able to specialize the function if your type doesn't have is_arithmetic<mytype>::value==true . You are allowed to specialize templates in the standard library. The following code compiles even though the mytype specialization of func doesn't use is_arithmetic:

#include <iostream>
#include <type_traits>
// firstsomething.hpp
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type func(const T& x) noexcept
{ return x; }
// something.hpp
class mytype {
};
namespace std {
template<> class is_arithmetic<mytype> {
static const bool value=1;
};
}
template <> mytype func(const mytype& x) noexcept { return mytype(); }
int main() {
func(0.0);
func(0);
}


If the is_arithmetic specialization was removed, the code would fail to compile on GCC 4.6. If your type is not an arithmetic type then I think you're going to have to use function overloading.

I think I was concerned that creating an overload would break func for integer types because mytype does not have an explicit constructor and it still takes a single argument integer value. However this is not the case apparently.

Yes; the compiler will prefer to instantiate a template over having a cast and using a non-template (although you can force it to use the non-template version by generating a function pointer to it and calling it, or you can force it to use a template by specifying the template arguments explicitly).

PARTNERS