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
.
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'
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.