Museful
Museful

Reputation: 6959

SFINAE check for template parameter operators

Could you tell me why the following code fails to compile (with "no matching overloaded function found" in MSVC):

template<typename V>
struct LinearModel { // has basis vectors
    template<typename T = V>
    auto consolidation() const -> decltype(std::declval<T>() += (std::declval<T>() *= double())) {
        V linearCombination;
        // linearly combine basis vectors using += and *=
        return linearCombination;
    }
};

int main(){
    LinearModel<double> lm;
    auto c = lm.consolidation(); // the line that produces the error
    return 0;
}

My intention is to define LinearModel<T>::consolidation() only for T that have T& operator *=(double) and T& operator +=(T).

Upvotes: 0

Views: 63

Answers (2)

Museful
Museful

Reputation: 6959

What I did in the end, based on @rafix07's answer:

    template<typename T = std::remove_reference_t<decltype(std::declval<V&>() += (std::declval<V&>() *= double()))>>
    T consolidation() const {
        T linearCombination;
        // ...
        return linearCombination;
    }

Upvotes: 0

rafix07
rafix07

Reputation: 20969

declval for T returns T&&, it is not allowed to assign result of *= (or other assignment operations) to R-value.

If you want to get Lvalue use: declval<T&>():

    -> std::remove_reference_t<decltype(std::declval<T&>() += (std::declval<T&>() *= double{}))> 

Live demo

Upvotes: 2

Related Questions