Hello concepts

By , last updated August 1, 2019

Some of the motivation behind concepts, is to be able to restrict template interfaces in an easy-to-use way. It is possible today using template meta programming and static_assert with C++03/C++11/C++14/C++17. However, the error messages are insanely detailed and it’s almost not possible to decipher them without a black belt in template programming. With any modern compiler, it’s usually 50-100 lines of errors for simple template mistakes.

With concepts, the promise is the error messages are to the point and will not take forever to compile. On the pedantic side, the error will manifest at lookup time and not at instanciation time.

To make sure your compiler actually do support concepts, here is some sample code to leverage concepts.

// hello-concepts.cpp
template<typename T>
requires true   // True concept
struct Foo
{};

template<typename T>
requires false  // False concept
struct Bar
{};

int main()
{
    Foo<int>(); // Ok
    Bar<int>(); // Fail
    return 0;
}

Build it with g++ with this command line:

$ g++ -fconcepts hello-concepts.cpp -o hello-concepts

The sample is intended to have a compile error:

hello-concepts.cpp: In function 'int main()':
hello-concepts.cpp:15:9: error: template constraint failure
  Bar<int>(); // Fail
         ^
hello-concepts.cpp:15:9: note:   constraints not satisfied
hello-concepts.cpp:15:9: note:   'false' evaluated to false

Comment out line with Bar<int>(); and it will build.

If there are no errors, everything is set for beginning the journey of learning concepts.

Troubleshooting compiler errors

If there are any other errors while building, you might have forgotten the -std=c++1z or -fconcepts command line option or the GCC version is too old.

$ g++ hello-concepts.cpp -o hello-concepts
hello-concepts.cpp:2:1: error: 'requires' does not name a type
 requires true        // 2: Concept require clause
 ^~~~~~~~
hello-concepts.cpp: In function 'int main()':
hello-concepts.cpp:7:2: error: 'Foo' was not declared in this scope
  Foo<int>();
  ^~~
hello-concepts.cpp:7:6: error: expected primary-expression before 'int'
  Foo<int>();
      ^~~

If you have an older version of GCC, there will be a slightly different error message.

$ g++ concepts-test.cpp -o concepts-test
concepts-test.cpp:2:1: error: 'requires' does not name a type
 requires true        // 2: Concept require clause
 ^
concepts-test.cpp: In function 'int main()':
concepts-test.cpp:7:2: error: 'Foo' was not declared in this scope
  Foo<int>();
  ^
concepts-test.cpp:7:6: error: expected primary-expression before 'int'
  Foo<int>();
      ^
concepts-test.cpp:7:6: error: expected ';' before 'int'

Assembly output

Concepts is a compile time only feature. If everything builds fine, there will be no mention or trace of concepts in the executable files. Even the assembly will not mention anything about concepts. And there will be no runtime penalty for using concepts.

Build hello-concepts.cpp with the -S command line switch to enable assembly output. Lack of optimized builds with -O is intended.

g++ -fconcepts hello-concepts.cpp -S -o hello-concepts.asm

The file hello-concepts.asm will be very similar to the following listing.

    .file   "hello-concepts.cpp"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    xorl    %eax, %eax
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (GNU) 7.0.0 20160704 (experimental)"
    .section    .note.GNU-stack,"",@progbits

There is no mention of any concepts or any requirements, which proves it’s only at compile time concepts and constraints are enabled and visible (internal to the compiler).

Professional Software Developer, doing mostly C++. Connect with Kent on Twitter.