Compiling the following code
template<typename T>
class t1 {
};
class t1 {
};
Gives the following error
error: template argument required for ‘class t1’
It's literally been years since I've used C++ enough to delve into templates (I've decided to pick it back up and learn C++ 11/14), so I'm probably mistaken, but I thought this was legal.
Can someone advise? If you wanted to do something like this, how would you go about doing it?
No, you can't do this.
Unlike a function template, a class template cannot be overloaded. t1 has been declared as a class template, the only thing you can do is specialize it:
template <>
class t1<int> {
};
You could do something like this with variadic templates:
template<typename...>
struct myclass;
template<>
struct myclass<>{};
template<typename T>
struct myclass<T>{};
But I can think of little use other than template metaprogramming and you still have to use template syntax: myclass<>
Related
In C++ there are 2 template types (to my knowledge): template classes and template functions. Why is it not possible to have a template of template? (be it class, or function, or other template). Has it ever been considered in standards? Does it break C++ syntax/spirit in a way?
I know it may sound crazy, and it's easy to get around.
What is possible with C++:
template<bool b>
class TemplateDependingOnBool
{
public:
template<typename T>
class TheTemplateWeWant{};
}
What would be great:
template<bool b>
template<typename T>
class TheTemplateWeWant{};
and call it in a policy-based style (that's where it's really interesting):
template<typename T, template<typename> class ThePolicy = TheTemplateWeWant<true> >
class Foo {};
The way it's possible to do now is to use:
template<typename T,
template<typename> class ThePolicy = TemplateDependingOnBool<true>::TheTemplateWeWant >
class Foo{};
which is not very elegant.
EDIT:
I know I can template on 2 parameters. The goal is to use the underlying template class (the templated template) as something by itself, be it in a template alias or a template template parameter (as shown in my example).
Policy-based design is a reference to Andrei Alexandrescu's Modern C++ Design, which is the main reason why the feature I'm asking might be useful (because templates are used as template parameters).
With C++11, you're wrong in assuming only two types of templates. There are also type aliases which allow
template <bool b, typename T>
class TheTemplateWeWant { ... };
template<typename T>
using ThePolicy = TheTemplateWeWant<true, T>
If I'm understanding what you're asking correctly (and I'm not entirely clear on your question), then you could write your template taking two parameters:
template <bool b, typename T>
class TheTemplateWeWant { ... };
add a metafunction to partially apply the bool:
template <bool b>
struct PartiallyWant {
template <typename T>
using type = TheTemplateWeWant<b, T>;
};
and then pass that as your policy:
template<typename T,
template<typename> class ThePolicy = PartiallyWant<true>::type >
class Foo { ... };
Foo<char, PartiallyWant<false>::type> foo;
So why not just layer the templates like you propose? The simple answer is that there's no reason to. If TheTemplateWeWant has two template parameters (bool b and typename T, regardless of whether it's an "inner" class or not), then we should express it as such. And if we want to only apply one type or the other, that's something that has fewer use-cases than a general template while also being solvable with just a few lines of boilerplate. Additionally, what if we had such a feature, and now I want to partially apply the T instead of the b? With a few lines of boilerplate I can again accomplish the same thing, but with the layering this would be impossible.
As far as i know you cand you simply that, and it works just as you want - class templated with 2 parameters.
template<bool b, typename T>
class TheTemplateWeWant{}; //valid in C++
What you're describing is partial binding of template parameters, just like std::bind can turn a binary function into a unary function.
For metaprogramming madness, there's Boost.MPL. They do have a template boost::mpl::bind.
When programming with C++ templates, I often find it useful to define a type alias member called type. I've defined a kind of "identity" template:
template <typename T>
struct id { using type = T; };
I quite like that I can then often avoid putting anything between the braces of a class definition; inheriting from an id specialisation instead. A trivial primary template example might then be:
template <typename,typename>
struct Foo : id<void> {};
Does something like id exist in the standard library; or Boost?
yes, sort of.
std::enable_if<true, T>
such is the code:
template<typename,int> class Uoo; //without this will result in complie error,why?
template<typename T>
class Uoo<T,1>
{
};
int main(){
return 0;
}
why Specialized template class need forward declaration?
The following code is a specialisation of a template.
template<typename T>
class Uoo<T,1>
{
};
But you haven't said what the unspecialised form is, and the language requires you to do that. So you need to add the prototype:
template<typename,int> class Uoo;
You don't actually need to declare the unspecialised form since an instance of it is never required. So a prototype is sufficient.
It's not actually a forward declaration that you're making. What you are doing is first defining the "pattern" of the templated class and then you're defining a specialized context or version of it. The better question is, if you didn't have a non-specialized case, then what would be the point of the 2nd template parameter?
As declared, template<typename T> class Uoo<T,1> is a partial specialization of template<typename,int> class Uoo; it fixes the int parameter to 1. It cannot be a partial specialization of a template that doesn't exist.
You could make your "real" class template self-sufficient by writing
template<typename T>
class Uoo
{
...
};
Okay, so I believe this is a pure c++ mucky syntax question.
I have a class defined with a ptr-to-member as one of its template parameters:
template <class T, T *T::*hook> class My_list {
I have another simple class that is a friend of this class. Usually, I would write:
class My_friend_class {
template <class, class> friend class My_list;
};
...but, because the second template parameter isn't that free...how do I state the friendship?
Thanks!
Maybe a better question is "Why?" rather than "How?"
Exactly what are you trying to achieve? When your C++ code becomes complex and ugly, it is often a warning that you are approaching a problem wrongly.
Sometimes when coding with C++ templates, you want to prevent users from instantiating a specific specialization or set of specializations, because the result would be nonsensical. So you can define a (specific or partial) specialization whose definition, if instantiated, would cause a compiler error. The goal would be, if a user "misuses" the template, to cause a compiler error right next to a comment in your header file explaining what not to do, rather than leaving the compiler to come up with some confusing error message by its own devices, or maybe allowing the questionable code to compile.
Example:
template <typename T> struct MyClassTemplate {
// ...
};
template <typename T> struct MyClassTemplate<T*> {
// Do not use MyClassTemplate with a pointer type!
typedef typename T::intentional_error err;
};
There are a number of ways to do this (depending on whether your specialization is a complete or partial specialization of a class or function). But the syntax used must (?) depend on a template parameter, or else the compiler will complain when it first parses the intentional-error definition. The example above has a hole in that somebody could stubbornly define an intentional_error nested type or member typedef (though I'd say they would then deserve whatever problems come up as a result). But if you use a trick too fancy, you're likely to get an indecipherable and/or misleading compiler error message, which mostly defeats the purpose.
Are there better straightforward ways to disallow template instantiations?
I'm aware that in C++0x, template Concepts and deleted function declarations will provide much better control over this sort of thing, but I'm looking for answers that are valid C++03.
You could just omit defining it.
template <typename T> struct MyClassTemplate<T*>;
You could also derive from a non-defined specialization
template <typename T> struct invalid;
template <typename T> struct MyClassTemplate<T*> : invalid<T> { };
Note that explicit specializations that declare classes or functions will never depend on template parameters. So, stuff like this that depend on template parameters can't work anyway. In that case, declaring a non-defined explicit specialization should be sufficient
template<> struct MyClassTemplate<int*>;
For me this sounds like a typical case for static_assert from C++0x or BOOST_STATIC_ASSERT. The static_assert functionality has the advantage that you can pass a custom error message so that the reason for the error is more clear.
Both ways are giving you the opportunity to prematurely end the compilation process under some custom defined compile time condition.
with static_assert:
template <typename T> struct MyClassTemplate<T*> {
static_assert(always_false<T>::value, "Do not use MyClassTemplate with a pointer type!");
};
with BOOST_STATIC_ASSERT
template <typename T> struct MyClassTemplate<T*> {
// Do not use MyClassTemplate with a pointer type!
BOOST_STATIC_ASSERT(always_false<T>::value);
};
Always false would look something like this:
template< typename T >
struct always_false {
enum { value = false };
};
HTH
Edit: Fixed the examples to make them actually work ;-) Thanks to GMan!
If you don't want to use a library, this construct is pretty reliable (it's roughly what Boost does internally):
template <typename T>
void must_be_specialized(T const&)
{
enum dummy { d = (sizeof(struct must_be_specialized_for_this_type)
== sizeof(T)) };
}
You can put something analogous in a specialization to disallow instantiation of the template with that type. I wouldn't, personally, worry about must_be_specialized_for_this_type gaining a definition from somewhere, but you could use a forward declaration to squirrel it away in a private namespace if you really wanted.
Concepts were removed from '0x. You can use a library, like Boost Concept Check.
"Are there better straightforward ways to disallow template instantiations?" Nothing significantly better than what you have already identified. I am pretty sure C++ protection mechanisms are there to protect you from accident not from malice. And someone defining a specialisation or a class to break your intended use I would consider malicious. Perhaps you could hit the person in the back of the head each time they do it.
I personally prefer to put the checks into templates that exist only to describe the checks. That allows interesting combinations of inheritance and templates.
template <class T>
class not_with_pointer_t { };
template <class T>
class not_with_pointer_t<T*>;
template <class T>
class some_class_t : public not_with_pointer_t<T> { };
template <class T, template <class U> class base_t>
class another_class_t : public base_t<T> { };
typedef some_class_t<int> a_t; // ok
typedef some_class_t<void*> b_t; // error if instantiated
typedef another_class_t<void*, not_with_pointer_t> c_t; // error if instantiated
template <class T> class unrestricted_t { };
typedef another_class_t<void*, unrestricted_t> d_t; // ok
boost::enable_if