www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Error: template instance does not match template declaration

reply Vitalii <yvitaliy1980 yandex.ru> writes:
Hello! I am getting the following error:
```
inst.d(8): Error: template instance `Worker!(Mode.Inspect)` does 
not match template declaration `Worker(mode : Mode)
```

when compile next code:
```
enum Mode { Inspect, Execute }

class Worker(mode : Mode) {
	this() {}
}

void main() {
	auto W = Worker!(Mode.Inspect)();
}
```
Can anybody suggest to me what I do wrong?
Nov 17 2021
parent reply Tejas <notrealemail gmail.com> writes:
On Wednesday, 17 November 2021 at 10:10:43 UTC, Vitalii wrote:
 Hello! I am getting the following error:
 ```
 inst.d(8): Error: template instance `Worker!(Mode.Inspect)` 
 does not match template declaration `Worker(mode : Mode)
 ```

 when compile next code:
 ```
 enum Mode { Inspect, Execute }

 class Worker(mode : Mode) {
 	this() {}
 }

 void main() {
 	auto W = Worker!(Mode.Inspect)();
 }
 ```
 Can anybody suggest to me what I do wrong?
```d enum Mode { Inspect, Execute } class Worker(Mode /*no need for template specialization :) */a) { this() {} } void main() { auto W = new/*Add new here, because this ais a class, not struct*/ Worker!(Mode.Inspect)(); }
Nov 17 2021
next sibling parent Tejas <notrealemail gmail.com> writes:
On Wednesday, 17 November 2021 at 12:19:05 UTC, Tejas wrote:
 On Wednesday, 17 November 2021 at 10:10:43 UTC, Vitalii wrote:
 Hello! I am getting the following error:
 ```
 inst.d(8): Error: template instance `Worker!(Mode.Inspect)` 
 does not match template declaration `Worker(mode : Mode)
 ```

 when compile next code:
 ```
 enum Mode { Inspect, Execute }

 class Worker(mode : Mode) {
 	this() {}
 }

 void main() {
 	auto W = Worker!(Mode.Inspect)();
 }
 ```
 Can anybody suggest to me what I do wrong?
```d enum Mode { Inspect, Execute } class Worker(Mode /*no need for template specialization :) */a) { this() {} } void main() { auto W = new/*Add new here, because this ais a class, not struct*/ Worker!(Mode.Inspect)(); }
Sorry for typo, I meant "is", not "ais" :(
Nov 17 2021
prev sibling parent reply Vitalii <yvitaliy1980 yandex.ru> writes:
Thank you for response, Tejas!

What I intended to do was make a class with only two states 
("Inspect" - do some analysis, "Execute" - do some stuff). That's 
why I tried to use template specialization.

The following code compiles successfully, but return *"fun with 
unknown"* instead of *"fun with Mode1"*, as I supposed. I think I 
missed some "static" thing in my code, but can't find any working 
examples. Any ideas?

```
import std.stdio : writeln;

enum Mode1;
enum Mode2;

class Worker(Mode) {
	this() {}

	void fun() {
		static if (is(typeof(Mode) == Mode1)) {
			writeln("fun with Mode1");
		}
		else static if (is(typeof(Mode) == Mode2)) {
			writeln("fun with Mode2");
		}
		else {
			writeln("fun with unknown");
		}
	}
}

void main() {
	auto W = new Worker!(Mode1)();
	W.fun();
}
```
Nov 17 2021
next sibling parent Tejas <notrealemail gmail.com> writes:
On Wednesday, 17 November 2021 at 12:55:15 UTC, Vitalii wrote:
 Thank you for response, Tejas!

 What I intended to do was make a class with only two states 
 ("Inspect" - do some analysis, "Execute" - do some stuff). 
 That's why I tried to use template specialization.

 The following code compiles successfully, but return *"fun with 
 unknown"* instead of *"fun with Mode1"*, as I supposed. I think 
 I missed some "static" thing in my code, but can't find any 
 working examples. Any ideas?

 ```
 import std.stdio : writeln;

 enum Mode1;
 enum Mode2;

 class Worker(Mode) {
 	this() {}

 	void fun() {
 		static if (is(typeof(Mode) == Mode1)) {
 			writeln("fun with Mode1");
 		}
 		else static if (is(typeof(Mode) == Mode2)) {
 			writeln("fun with Mode2");
 		}
 		else {
 			writeln("fun with unknown");
 		}
 	}
 }

 void main() {
 	auto W = new Worker!(Mode1)();
 	W.fun();
 }
 ```
You're not using a normal template here, you're using a template that takes non-type parameters(basically you're using a template that takes __variables__ as parameters rather than __types__) ```d import std.stdio : writeln; enum Mode{ Mode1, Mode2 } //enum Mode2; You're creating two completely different enum types, why??? This a mistake or intentional? class Worker(Mode m) { this() {} void fun() { static if (m == Mode.Mode1) /*You can't write Mode1 directly, use enumType.enumValue :(*/{ writeln("fun with Mode1"); } else static if (m == Mode.Mode2) { writeln("fun with Mode2"); } else { writeln("fun with unknown"); } } } void main() { auto W = new Worker!(Mode.Mode1)(); W.fun(); } ```
Nov 17 2021
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/17/21 7:55 AM, Vitalii wrote:
 Thank you for response, Tejas!
 
 What I intended to do was make a class with only two states ("Inspect" - 
 do some analysis, "Execute" - do some stuff). That's why I tried to use 
 template specialization.
Template parameters are of 3 types: 1. A type parameter. This has a single symbol name, and represents a type *provided by the caller*. ```d enum Mode { a, b } class Foo(Mode) { // inside here, `Mode` is a locally named type, not the enum } // usage Foo!int; ``` 2. A template value. This is specified by using 2 names, the type of the value, and the name for the value to be used internally. ```d class Foo(Mode mode) { // NOW `Mode` is referring to the type of `mode`, and // `Mode` is the external type, not a local type } // usage Foo!(Mode.a); ``` 3. An alias to a symbol, type, or value. This is specified using the keyword `alias` and then a name for the aliased symbol or value. This is probably the most versatile, and you can use this as a last resort if you aren't specifically interested in types or values, or you want a value that is of unknown type. ```d class Foo(alias mode) { // `mode` can be anything. } // usage Foo!int; Foo!(Mode.a); Foo!5; Foo!writeln; ``` Aside from those 3 basic template parameter mechanisms, there is specialization which provide a *specialized* template implementation *if the arguments match or implicitly can convert to the specialization*. I know there are some languages that use this syntax to specify the type of a parameter, but D does not. Note that alias specialization is not allowed. ```d enum Mode { a, b} class Example(T : int) { pragma(msg, "specialized ", typeof(this)); } class Example(T : Mode) { pragma(msg, "specialized2 ", typeof(this)); } class Example(T) { pragma(msg, "unspecialized ", typeof(this)); } Example!int a; // => "specialized Example!int" Example!short b; // => "specialized Example!short" Example!string c; // => "unspecialized Example!string" Example!Mode d; // => "specialized2 Example!Mode" class Example2(Mode mode : Mode.a) { pragma(msg, "specialized ", typeof(this)); } class Example2(Mode mode) { pragma(msg, "unspecialized ", typeof(this)); } Example2!(Mode.a) e; // specialized Example2!Mode.a Example2!(Mode.b) f; // unspecialized Example2!Mode.b ``` I hope this helps you understand how to properly write these. -Steve
Nov 17 2021
parent Vitalii <yvitaliy1980 yandex.ru> writes:
On Wednesday, 17 November 2021 at 18:00:59 UTC, Steven 
Schveighoffer wrote:
 On 11/17/21 7:55 AM, Vitalii wrote:
 [...]
Template parameters are of 3 types: 1. A type parameter. This has a single symbol name, and represents a type *provided by the caller*. [...]
Steve, thank you very much for the detailed answer! Much has become clearer.
Nov 17 2021