Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - Template argument deduction/substitution failed

Tags:

c++

templates

My goal is to be able to use arithmetic operators on std::vector. Consider the following example:

#include <vector>

using namespace std;

template <class S, class T, class U> vector<U> operator+(const vector<S> &a, const vector<T> &b){
    vector<U> result;
    result.reserve(a.size());
    for(int i = 0; i < a.size();++i){
        result[i] = a[i] + b[i];
    }
    return result;
}

int main(int argc, char** argv) {
    vector<double> bla;
    bla = bla + bla;
    return 0;
}

This code does not compile because the compiler is not able to deduce template argument U (it's not an MWE but I tried to provide an example that makes sense). Why is this the case? I know that it might not make sense to use three template arguments here. My idea was that in the case where types S and T both provide a matching '+'-implementation with different return types, I could handle both cases at once. Or would then be a problem with ambiguity? I'm just wondering if the compiler shouldn't be able to deduce U. Of course the following code just works fine:

#include <vector>

using namespace std;

template <class S, class T> vector<S> operator+(const vector<S> &a, const vector<T> &b){
    vector<S> result;
    result.reserve(a.size());
    for(int i = 0; i < a.size();++i){
        result[i] = a[i] + b[i];
    }
    return result;
}

int main(int argc, char** argv) {
    vector<double> bla;
    bla = bla + bla;
    return 0;
}
like image 325
Severin Avatar asked Oct 31 '22 19:10

Severin


1 Answers

You can accomplish this with the use of common type

#include <vector>
#include <type_traits>

using namespace std;

template <class S, class T> 
vector<typename std::common_type<S, T>::type> operator+(const vector<S> &a, const vector<T> &b)
{
    vector<typename std::common_type<S, T>::type> result;
    result.reserve(a.size());
    for(unsigned int i = 0; i < a.size();++i){
        result[i] = a[i] + b[i];
    }
    return result;
}

int main() {
    vector<double> bla;
    bla = bla + bla;
    return 0;
}

Live Example

Edit: as Jarod42 suggested, you might also use vector<decltype(a[0] + b[0])> as another possible return type (which may be different than the common_type). Keep in mind that this latter one requires trailing return type or std::declval (C++11)

like image 80
Marco A. Avatar answered Nov 12 '22 21:11

Marco A.