3

It's probably just that the concept is bad, but I can't see why. And didn't find any example with constructor. Or maybe it has nothing to do with the constructor...

template < typename T >
concept bool C_Object() {
  return requires {

    T();
  };
}

template < C_Object Object>
class  DefaultManager {

  //  Content;
};

template < C_Object Derived >
class  Component {

  // Content
};

struct Test : public Component<Test> {

  int data;

  Test() = default;
};

int main() {

  Test test;
  return 0;
}

Give the error :

test2.cpp:21:36: error: template constraint failure
 struct Test : public Component<Test> {
                                    ^
test2.cpp:21:36: note:   constraints not satisfied
test2.cpp:2:14: note: within ‘template<class T> concept bool C_Object() [with T = Test]’
 concept bool C_Object() {
              ^~~~~~~~
test2.cpp:2:14: note: the required expression ‘T()’ would be ill-formed

That sound like a : "Hey my code is broken, please fix it", sorry.

Anyway thanks

Have a great day

2
  • 1
    You know that concepts didn't make it to the standard? Commented Nov 28, 2016 at 20:42
  • @SergeyA yes probably c++20 Commented Nov 28, 2016 at 20:44

2 Answers 2

14

The problem is here:

struct Test : public Component<Test> {

Whenever you so much as name a specialization of a constrained class template, the given parameters are validated against the constraints. In this particular case, that means that C_Object<Test> is checked for satisfaction, but since Test is incomplete - the compiler hasn't parsed its definition yet - C_Object is not satisfied.

This is the "concepts" version of the classical problem with CRTP bases: you must delay inspection of the derived class until its definition is complete.

Sign up to request clarification or add additional context in comments.

5 Comments

I even didn't know about CRTP. Too much for this night I think. If you're crazy enough I love an explanation :) But anyway I'm really lucky that you was there. PS : I'll close the question when I'll read about CRTP and stuffs (Tomorrow).
Even on StackOverflow : stackoverflow.com/questions/19886041/… I didn't find why my code is not working, the CRTP seems to be okay (works perfect without concepts). I must delay inspection of the derived class as you said, but can't find any information about that.
@MathieuVanNevel the usual way I achieve the delaying you mention is by making sure to make the types re-dependent, informally speaking (i.e. I'm really using an actually dependent type).
That seems to be tricky with the constructor, but I'll try something. Thanks for the code, I was thinking it was not necessary. There is a lot of meta programming tricky like this?
@MathieuVanNevel as a heads-up that particular technique cannot work for things that can't be templates, such as the copy/move constructors and assignment operators as well as the destructor. it works for constructor templates though.
5

I found the most readable option to be an "impl" method with a constrained return type. Let's take the example in Luc Danton's comment and transfer it to C++20:

template <typename Var>
concept Fooable = requires(Var var) {
  {var.foo()};
};

template <typename Derived>
struct mixin {
  void bar() { impl().foo(); }
  Fooable auto& impl() { return static_cast<Derived&>(*this); } // Constrain return here!
};

// no constraint violation
struct ex1 : mixin<ex1> {
  void foo() {}
};

// no violation either
struct ex2 : mixin<ex2> {};

int main() {
  // mixin<ex1>::bar constraints respected
  ex1{}.bar();

  // mixin<ex2>::bar constraints violation
  ex2{}.bar();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.