|
|
|
|
|
by AndyKelley
2329 days ago
|
|
Here's the C++ example from the article: template <class T>
concept SignedIntegral = std::is_integral_v<T> &&
std::is_signed_v<T>;
template <SignedIntegral T> // no SFINAE here!
void signedIntsOnly(T val) { }
Here's the equivalent Zig code. You can run this with `zig test example.zig`. const std = @import("std");
const assert = std.debug.assert;
fn signedIntsOnly(val: var) void {
comptime assert(std.meta.trait.isSignedInt(@TypeOf(val)));
}
test "concepts example" {
var x: u32 = 1234;
signedIntsOnly(x);
}
This produces the compile error: ../lib/std/debug.zig:221:14: error: unable to evaluate constant expression
if (!ok) unreachable; // assertion failure
^
./example.zig:5:20: note: called from here
comptime assert(std.meta.trait.isSignedInt(@TypeOf(val)));
^
./example.zig:10:19: note: called from here
signedIntsOnly(x);
^
./example.zig:8:26: note: called from here
test "concepts example" {
^
It accomplishes the same thing, just a bit more verbose, since it is using the general tools of the language rather than special syntax. |
|
well yes, that's my point. You could also write
in C++ but it's quite preferable to refactor this inside the types themselves (for the same reason that you want to refactor any other kind of code in general - besides you don't want to go read the implementation of your functions every time do you ? IDEs show us only prototypes for a reason).How would you for instance specialize a generic function in Zig ? Does zig accept
and in another module and properly dispatches between both ?I'd be hard pressed to say that it is "as powerful" given what I'm seeing for now.