Search code examples
c++templatesstdset

Template argument deduction/substitution failed with std::set


I've looked through a lot of posts that get the same error, but couldn't find one that applied to my problem, apologies if this is a duplicate regardless.

Anyway my task is making a class called set_helper which makes std::sets a little easier to use. set_helper takes a set as its constructor parameter, and to help with template type deduction I also have to make a function called make_set_helper that is supposed to make type deduction easier. I don't fully understand what that means, so here's what I tried.

MRE with main.cpp and sethelp.h

main.cpp

#include<set>
#include "sethelp.h"

int main()
{
    std::set<int, std::greater<int> > sg;
    sg.insert( 0 );
    sg.insert( 1 );

    make_set_helper( sg );
    return 0;
}

sethelp.h

#pragma once

template<class T>
class set_helper
{
private:
    std::set<T>* s;
public:
    set_helper(std::set<T>& s) { this->s = &s; }
    bool operator==(T other) { return this == other; }
    std::set<T>* get_set() {return this->s;}
};
template<class T>
set_helper<T> make_set_helper(std::set<T>& s)
{
    return set_helper(s);
}

Here's the error message

 error: no matching function for call to ‘make_set_helper(std::set<int, std::greater<int> >&)’
  108 |   make_set_helper( sg ) += sih;
 note: candidate: ‘template<class T> set_helper<T> make_set_helper(std::set<T>&)’
   79 | set_helper<T> make_set_helper(std::set<T>& s)
 note:   template argument deduction/substitution failed:
 note:   mismatched types ‘std::less<_Key>’ and ‘std::greater<int>’

Why are the types mismatched and what should I do to fix it?


Solution

  • std::set<T> and std::set<T, std::greater<int>> are completely different types. Here's a more generic version:

    template<
        class Key,
        class Compare = std::less<Key>,
        class Allocator = std::allocator<Key>
    > 
    auto make_set_helper(std::set<Key, Compare, Allocator>& s)
    {
        return set_helper(s);
    }
    

    The class itself should also have all these template parameters. Alternatively:

    template<class ...P> 
    auto make_set_helper(std::set<P...>& s)
    {
        return set_helper(s);
    }