• 0

[C++] templates


Question

What's wrong with my code and how can I fix it? I have tried numerous possibilities. The main() shows what I'm trying to achieve, and just above is where I get the compiler error. This is Visual Studio 2008.

template<typename T>
struct myStruct {
	static void write() {
	}
};

template<typename T, typename S>
struct myStruct {
	static void write() {
	}
};
// C2977: 'myStruct' : too many template arguments
int main() {
	myStruct<int>::write();
	myStruct<int, int>::write();
}

Edited by Dr_Asik
Link to comment
Share on other sites

10 answers to this question

Recommended Posts

  • 0

No C++ gurus on Neowin? Basically I'm trying to achieve the equivalent of this C# code:

	class MyClass<T> {
		public static void method() {
		}
	}

	class MyClass<T, S> {
		public static void method() {
		}
	}

	class Program {
		static void Main(string[] args) {
			MyClass<int>.method();
			MyClass<int, int>.method();
		}
	}

where there are two classes with the same name but different number of generic parameters. Is that possible at all using templates in C++?

Link to comment
Share on other sites

  • 0

Thanks but that's not what I'm looking for. I want two different class definitions, with two different implementations of write(). So when you call myStruct<int, int>::write(), it's not the same code as myStruct<int>::write(). A bit like template specialization.

This example may seem contrived as there are probably much cleaner ways of doing this, but what I'm really trying to do is more complex than that and I need the templates.

Link to comment
Share on other sites

  • 0
Is that possible at all using templates in C++?

Apparently not, judging from the error my compiler gave (which appears to be explicit on the topic than the one your compiler provided)

error C2983: 'myStruct' : new template parameter list has more parameters than the previous declaration
error C2953: 'myStruct' : template class has already been defined

Link to comment
Share on other sites

  • 0

Okay. :huh: I've seen similar code before though, I think it used partial template specialization. I will have to investigate the issue. Thanks.

Link to comment
Share on other sites

  • 0

I wonder if it might be a limitation of the compiler and not the language itself (I've never tried doing this before, so I'm not sure). I should try this in g++ and see how it handles it... Edit: nope, it doesn't like it either

Edited by code.kliu.org
Link to comment
Share on other sites

  • 0

#include &lt;stdio.h&gt;

template&lt;typename T, typename S&gt;
struct myStruct {
	static void write() {
		printf("foo\n");
	}
};

template&lt;typename T&gt;
struct myStruct&lt;T, void&gt; {
	static void write() {
		printf("bar\n");
	}
};

int main() {
	myStruct&lt;int, int&gt;::write();
	myStruct&lt;int, void&gt;::write();
}

When run, this prints

foo
bar

It's not as pretty, but oh well...

Link to comment
Share on other sites

  • 0

Yeah you're getting there. It has something to do with specifying the type parameters on the class declaration. Thanks for the help, I'll ask the question to my supervisor who is a C++ template genius and I'll report here.

Link to comment
Share on other sites

  • 0

What I did was use partial template specialization, which Microsoft documents here and here. The limitation to this is that each specialized definition must have the same number of template parameters as the base definition, which is why it was necessary to throw a void in there (which some clever use of preprocessor macros could help squirrel away ;)). If there's another way to do this, I'd be curious to find out...

Link to comment
Share on other sites

  • 0

Ok, I got it by myself. This stuff is pretty neat. Typical of C++, you have to use a somewhat unrelated feature to get where you want: here it's function pointers.

#include &lt;iostream&gt;
using namespace std;

template &lt;typename T&gt;
struct MyStruct {
	static void say() {
		cout &lt;&lt; "generic" &lt;&lt; endl;
	}
};

template &lt;typename T&gt;
struct MyStruct&lt;T*&gt; {
	static void say() {
		cout &lt;&lt; "T is a pointer type" &lt;&lt; endl;
	}
};

template&lt;&gt;
struct MyStruct&lt; void (*) &gt; {
	static void say() {
		cout &lt;&lt; "T is a function pointer of type [void something(...)]" &lt;&lt; endl;
	}
};

template&lt;typename arg1&gt;
struct MyStruct&lt; void (*)( arg1) &gt; {
	static void say() {
		cout &lt;&lt; "T is a function pointer of type [void something(arg1)]" &lt;&lt; endl;
	}
};

template&lt;typename arg1, typename arg2&gt;
struct MyStruct&lt;void (*)(arg1, arg2)&gt; {
	static void say() {
		cout &lt;&lt; "T is a function pointer of type [void something(arg1, arg2)]" &lt;&lt; endl;
	}
};

int main() {
	MyStruct&lt;int&gt;::say();
	MyStruct&lt;int*&gt;::say();
	MyStruct&lt;void (*)&gt;::say();
	MyStruct&lt;void (*)( int)&gt;::say();
	MyStruct&lt;void (*)( int, float)&gt;::say();
	system("pause");
}

So basically I can add as many function parameters as I want, and that makes their types available in the template class. So if I want a MyStruct specialization with 5 template arguments, I just call MyStruct<void (*) (Type1, Type2, Type3, Type4, Type5)>, and that invokes code specific to 5 template arguments.

I still think the C# code is a hell of a lot more intuitive, but it was fun figuring this out.

Edited by Dr_Asik
Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.