onqtam
onqtam

Reputation: 4548

trouble using SFINAE for templated constructor

What is the difference between the following 2:

template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
explicit Approx(const T& value) {}

vs

template <typename T>
explicit Approx(const typename std::enable_if<std::is_constructible<double, T>::value, T>::type& value) {}

Approx is the constructor of a normal class (not templated) and I need types that double is constructible from

My problem is that the first one works, but is not C++98 (default template argument, etc. - I have my own c++98 traits for enable_if and is_constructible)

The reason I'm asking is because I want to support strong typedefs of double:

class Volatility {
    double underlying_;
public:
    explicit Volatility(double u) : underlying_(u) {}
    explicit operator double() const { return underlying_; }
};

Approx(Volatility(1.)); // error

Upvotes: 2

Views: 231

Answers (1)

Dave S
Dave S

Reputation: 21123

Your C++03 version doesn't work because it can't deduce T, given the argument. The usual C++03 mechanism for constructors is an extra default argument.

template<typename T>
explicit Approx(const T& value, typename std::enable_if<std::is_constructible<double, T>::value>::type* dummy = 0) {}

T is deducible in this form, and if T meets the expectations specified by enable_if, the extra argument ends up being void*.

Upvotes: 4

Related Questions