range_primitives_helper ~master

A library to help with std.range primitives like isInputRange


To use this package, run the following command in your project's root directory:

Manual usage
Put the following dependency into your project's dependences section:

Range Primitives Helper

Range primitives like isInputRange are used in many places in D code. When the usage of those primitives leads to a compile error, because e.g. the passed type is not an InputRange, the error messages are often not very helpful. This is especially true, if range primitives are used as function constraints for function overloading.

For example:

void fun(T)(T t) if(isInputRange!T && !isRandomAccessRange!T) {
}

void fun(T)(T t) if(isRandomAccessRange!T) {
}

This is at least annoying, and avoidable at best. This library Range Primitives Helper helps making this less annoying.

Usage

import range_primitives_helper;

enum string result = isInputRangeErrorFormatter!(T);

If the passed type T is an InputRange the enum string result will read

T.stringof ~ " is an InputRange"

if T is not an InputRange the string will list which criteria of the InputRange concept is not fulfilled by T;

But this is only half the work. The other part is a bit of a refactoring effort. Instead of having to template functions that use function constraints to do the overload resolution, a better approach is to have what I would call a dispatch function like this.

import range_primitives_helper;

void fun(T)(T t) {
	static if(isRandomAccessRange!T) {
		funRAR(t);
	} else static if(isInputRange!T) {
		funIR(t);
	} else {
		static assert(false, "'fun' expected 'T' = "
			~ T.stringof ~ " either to be
			~ an InputRange or"
			~ " a RandomAccessRange but\n"
			~ isInputRangeErrorFormatter!(T)
			~ "\n"
			~ isRandomAccessRangeErrorFormatter!(T));
	}
}

private void funIR(T)(T t) {
}

private void funRAR(T)(T t) {
}

Calling fun with an int for example results in, IMO very nice, error message

SOURCE_LOCATION: Error: static assert:  "
'fun' expected 'T' = 'int' either to be an InputRange or a RandomAccessRange but
int is not an InputRange because:
	the property 'empty' does not exist
	and the property 'front' does not exist
	and the function 'popFront' does not exist
int is not an RandomAccessRange because
	the property 'empty' does not exist
	and the property 'front' does not exist
	and the function 'popFront' does not exist
	and the property 'save' does not exist
	and int must not be an autodecodable string but should be an aggregate type
	and int must allow for array indexing, aka. [] access"

If we call fun with a custom struct that looks like

struct Thing {
	void popFront();
	@property int front() { return 0; }
}

we get the error string

SOURCE_LOCATION: Error: static assert:  "
'fun' expected 'T' = 'Thing' either to be an InputRange or a RandomAccessRange but
Thing is not an InputRange because:
	the property 'empty' does not exist
Thing is not an RandomAccessRange because
	the property 'empty' does not exist
	and the property 'save' does not exist
	and must allow for array indexing, aka. [] access"

Primitives

The are primitives for:

Typestd.rangerange_primitives_helper
InputRangeisInputRangeisInputRangeErrorFormatter
BidirectionalRangeisBidirectionalRangeisBidirectionalRangeErrorFormatter
ForwardRangeisForwardRangeisForwardRangeErrorFormatter
RandomAccessRangeisRandomAccessRangeisRandomAccessRangeErrorFormatter
OutputRangeisOutputRangeisOutputRangeErrorFormatter
Authors:
  • Robert burner Schadek
Dependencies:
none
Versions:
1.0.0 2022-Jan-05
~master 2022-Jan-05
Show all 2 versions
Download Stats:
  • 0 downloads today

  • 0 downloads this week

  • 0 downloads this month

  • 6 downloads total

Score:
0.4
Short URL:
range_primitives_helper.dub.pm