using concepts instead of SFINAE - Having trouble

I was able(with a lot help from the forum) to implement SFINAE in my std::list implementation.

But in that time I couldn't use concepts so now that I can I don't know how.
I saw may examples with concepts and I get the examples fine.

But didn't find any that would constrain a template to be of type input_interator only and I can't seem to figure it out.

This is the stripped down version of the code that I want to replace with concept.

1
2
3
4
5
6
7
8
9
10
11
12
template <typename T>
class List
{
   template <typename Iter>
   using required_input_iterator = std::enable_if<std::is_base_of_v<std::input_iterator_tag,
          typename std::iterator_traits<Iter>::iterator_category >>;

public: 
   template<typename InputIterator, typename = required_input_iterator<InputIterator>> 
List(InputIterator first, InputIterator last);

};


How can I achieve the above with concepts?

Also I tried to use some examples of concept I found inside a class and they don't work
1
2
3
4
5
6
7
8
9
class Test
{
    template <typename T>
    concept integ = std::is_integral_v<T>;
};
/code]

It throws this error:
[code]error: concept 'integ' not in namespace scope|


Why this happens?
Last edited on
That most likely means that concept cannot be used within a class or struct. Just withing a namespace.
That most likely means that concept cannot be used within a class or struct. Just withing a namespace.
That's what I am thinking.

I was able to implement concept to replace SFINAE though.

1
2
template <typename T>
concept RequiredInputIterator = std::input_iterator<T>;


Links that helped achive that:
https://core.ac.uk/reader/232670550
https://en.cppreference.com/w/cpp/iterator/input_iterator
https://en.cppreference.com/w/cpp/iterator

That most likely means that concept cannot be used within a class or struct. Just withing a namespace.
That's what I am thinking.

I was able to implement concept to replace SFINAE though.

1
2
template <typename T>
concept RequiredInputIterator = std::input_iterator<T>;



Links that helped achive that:
https://core.ac.uk/reader/232670550
https://en.cppreference.com/w/cpp/iterator/input_iterator
https://en.cppreference.com/w/cpp/iterator
It works like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iterator>
#include <list>
template <typename T>
struct List
{
   template<typename II> requires std::input_iterator<II>
   List(II first, II last) {}
};

int main() {
    std::list<int> l;
    
    List<int>(l.begin(), l.end()); // OK
    
    List<int>(1, 10); // Error: constraints not satisfied
}

live demo https://wandbox.org/permlink/D2BGrBkZQIJkRcha

concept RequiredInputIterator = std::input_iterator<T>;
that just renames the standard concept unnecessarily
Last edited on
that just renames the standard concept unnecessarily

Thanks
But what do you mean exactly by
renames the standard concept unnecessarily
?
"unnecessarily" as in It's much like if you were to do std::ostream& MyCoolCout = std::cout;, and then write all output in your program with MyCoolCout << "hello world\n";.
Such an alias It doesn't add anything.
But doing the way you said would need to write template<typename II> requires std::input_iterator<II> every time I need to constrain a template to only use std::input_iterator, wouldn't it be easier to just create the concept like I did?
std::input_iterator is already the concept you're looking for.
Both
template <std::input_iterator T> void f();
and
template <RequiresInputIterator T> void f();
behave the same.
Last edited on
Topic archived. No new replies allowed.