Use concepts to test for member functions

Hey guys,
I'd like to use concepts to verify that an interface is implented correctly.
Usally I would use virtual functions for this. However in this particular case the used implementation of the interface is known at compile time. There is no need for run time overheader like virtual functions.

I did come up with this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//Interface
#pragma once

#include <concepts>
#include <string_view>

template <typename T>
concept IDmmy = requires(T a, const std::string_view b)
{
  { a.foo() };
  { a.bar(b) };
};



class DummyImpl
{
public:
#if 1
  //not working with return type
  template<typename T>
  T foo();

  template<typename S>
  S bar(const std::string_view b);

#else
  //working without return type
  void foo();
  void bar(std::string_view);

#endif
};



=> I'm explicitly ommiting return values of foo and bar because they depend on template parameters. I thought this would things much more difficult.
However the version with return types dos not work because the concept evalutates to false.
Could you help me out figure why?

thx guys :)
Last edited on
The compound requirement on line 10 of your example
{ a.foo() };
Tests that the expression a.foo() is valid. It's not valid for your class because the compiler can't deduce what argument to substitute for the template parameter T in foo (or bar.)

This program exhibits the same root problem:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class DummyImpl
{ 
public:
  template<typename T> T foo() { return {}; } 
};

int main()
{  
  DummyImpl a;
  a.foo(); // error: no matching function for call to 'DummyImpl::foo()'
           // ...
           // note:  template argument deduction/substitution failed:
           // note:  couldn't deduce template parameter 'T'         
}

Often template arguments can be deduced, but not here. You'll have to specify it yourself:
a.foo<int>()

To fix the original program, specify the template argument in the concept as well:
1
2
3
4
5
6
7
template <typename T, typename U, typename V>
concept IDmmy = requires(T a, const std::string_view b)
{
  { a.foo<U>() };  // wrong: should be { a.template foo<U>() };
  { a.bar<V>(b) }; // wrong: should be { a.template bar<V>(b) };
  // or: { a.template foo<int>() };
};
Last edited on
Hey mbozzi,
thx for your answer. This makes sense.
However your proposed solution causes a compiler syntax error (at least on latest MSVC17)

error C2760: Syntaxerror: „)“ was not expected but Expression.
Do you know how to fix this?

If I'm trying to apply this concept to a test function I'm also getting ac ompiler error

1
2
3
4
5
6
7
8
9
10
11
12
13
template<IDmmy<int, int> DummyImpl>
void test(DummyImpl a)
{
  std::cout << "Just for testing " << a.foo<int>() << std::endl;
}

int main()
{
  DummyImpl testInstance;
  test(testInstance); //< Compiler error, concept evalutes to FALSE
  std::cout << "Hello CMake." << std::endl;
  return 0;
}


do you have an idea why this is happening?

thx for your help :)
do you have an idea why this is happening?
foo and bar are dependent names that must be disambiguated using the keyword template as follows
1
2
3
4
5
6
template <typename T, typename U, typename V>
  concept IDmmy = requires(T a, const std::string_view b)
  {
    { a.template foo<U>() };
    { a.template bar<V>(b) };
  };


Sorry for the typo.

Here's an example that compiles:
https://coliru.stacked-crooked.com/a/172953d0ad96c86a
Last edited on
AH thx alot,
now it's working fine :)
Topic archived. No new replies allowed.