This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 3 years ago.
I found this article:
https://tristanbrindle.com/posts/beware-copies-initializer-list
and I have some question about part of the presented code:
First:
I think that is something about dependent name but I am not sure what is a purpouse of this part:
template <typename T>
typename instance_counter<T>::counter instance_counter<T>::icounter{};
And second one:
template <typename T>
struct counted : T, private instance_counter<T>
{
using T::T;
};
Could somebody give me an explanation about these codes?
Could somebody give me an explanation about these codes?
template <typename T>
typename instance_counter<T>::counter instance_counter<T>::icounter{};
This is the initialization of a static variable declared in the instance_counter template (see the static struct counter { /* ... */ } icounter; in the blog post). See this thread for more info on the initialization of static data members. The definition refers to a nested name of a template (counter), and the compiler defaults to consider it a name for a value, not a type. To change this default interpretation, you need to prepend typename. See this thread for details.
template <typename T>
struct counted : T, private instance_counter<T>
{
using T::T;
};
Here, the template counted inherits publicly from T (public inheritance is the default for structs) and privately from instance_counter<T>. The public inheritance part together with using T::T (which brings in all ctor overloads of T) is used to provide the same interface as the class the template is instantiated with (e.g. string in the post). The private inheritance part means is-implemented-in-terms-of and makes sure the instance_counter machinery is pulled in for the newly instantiated class type, with the output being generated in the destructor.
Related
This question already has answers here:
How to force template <class> to be derived from BaseClassA?
(3 answers)
Closed 2 years ago.
In Java generic, when I want to ensure that the type of some generic class must inherit a class, I can code as below:
public class MyHandler<T extends Serializable> {}
This means that T must extend/implement the class/interface Serializable, otherwise, the compiler will generate an error.
How to get the same thing in C++11? I mean, if I code C++11 as below:
template<typename T>
class MyHandler {}
In this piece of code, T can be any class. But, if I want to tell the class users that T must inherit the class boost::archive::text_oarchive (just like <T extends Serializable> in Java), what can I do?
You can use std::is_base_of for checking.
template<typename T>
class MyHandler {
static_assert(std::is_base_of<boost::archive::text_oarchive, T>::value, "T must inherit boost::archive::text_oarchive");
};
Since C++20 we can use constraint, e.g.
template<typename T> requires std::is_base_of_v<boost::archive::text_oarchive, T>
class MyHandler {};
This question already has answers here:
Member function template selection and SFINAE
(1 answer)
SFINAE not working to conditionally compile member function template
(1 answer)
Approaches to function SFINAE in C++
(2 answers)
Closed 2 years ago.
I want to switch between to members of a templatized class based on the fact the type of the template is default constructible or not.
I think I'm not far from the solution after a lot of reading and tries around std::enable_if and std::is_default_constructible, but I'm still stuck at compile-time, here's a minimized exemple :
template<typename DataType>
class MyClass{
public:
template < typename = typename std::enable_if_t<std::is_default_constructible_v<DataType>>>
inline void createNew(unsigned int index) {
new (&this->buffer[index]) DataType(); // "placement new"
}
template < typename = typename std::enable_if_t<!std::is_default_constructible_v<DataType>>>
inline void createNew(unsigned int index) {
throw BaseException("No default constructor");
}
};
This last try results on "member function already defined or declared". I think I miss something, but I don't understand why both functions are selected for compilation even if they have the exact opposite template condition.
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 3 years ago.
I'm trying to get this to work:
template<template<typename> class... Attributes>
struct Skills
{
template<class DERIVED>
struct Create : public Attributes<DERIVED>...
{};
};
template <class T, class SKILLS>
class Tester : public typename SKILLS::Create<Tester<T,SKILLS>>
{}
but the compiler complains with:
error C2518: keyword 'typename' illegal in base class list; ignored
This works fine if I don't derive within a class template, however.
Is there any chance to derive from the nested template class?
Why do I need that? I'm trying to implement a nicer interface for a CRTP-class template, which allows doing something like:
using MyClass = ClassWithAttributes<Skills<Plus,Minus,Equal,Clear,Size>>
You have to write
template <class T, class SKILLS>
class Tester : public SKILLS::template Create<Tester<T,SKILLS>>
{ };
I mean
(1) no typename: in the list of base classes is implicit that the arguments are types
(2) you need template, before Create
(3) use SKILLS as argument of Tester, not Skills, because you have declared the template parameter SKILLS
(4) remember the semicolon at the end of class definition
This question already has an answer here:
Wrapping each type in a variadic template in a templated class
(1 answer)
Closed 4 years ago.
I'd like to be able to declare a class with a template pack, such that the class itself will have a member variable tuple that wraps each of the template pack members in a container type of some sort. A basic goal would look like:
template <typename Types...>
class VectorOfMembers
{
public:
// Member tuple where each element is expanded in a container
std::tuple<std::vector<Type[1]>, std::vector<Type[2]>, std::vector<TypeN...>>
};
Ideally I'd like to be able to do this with any templated object as the wrapping type too.
Well, you almost had it:
template <typename... Types>
class VectorOfMembers
{
public:
// Member tuple where each element is expanded in a container
std::tuple<std::vector<Types>...> tuple;
};
I have the following function defined inside my linked list class. The declaration in the header file looks like this:
template <typename T>
class RingBuffer
{
...//stuff
static BLink * NewLink (const T&); // allocator
};
BLink is a "link" class within the RingBuffer class. The following implementation code:
template <typename T>
RingBuffer<T>::BLink * RingBuffer<T>::NewLink( const T& t ) // this is line 114
{
// create a new link in linked list
....
....
}
Is giving me this compile error:
./ringbuff.cpp:114: error: expected constructor, destructor, or type conversion before â*â token
I am stumped as to why it it needs an expected constructor, destructor, or type conversion before the return value.
The problem here is that you are referring to a nested dependent type name (i.e. BLink is nested inside RingBuffer which is dependent on a template parameter)
You need to help your compiler a little in this case by stating that RingBuffer<T>::BLink is an actual type name. You do this by using the typename keyword.
template <typename T>
typename RingBuffer<T>::BLink * RingBuffer<T>::NewLink(const T& t)
{
// ...
}
Explanation:
The compiler cannot know if RingBuffer<T>::BLink is a type name or a static member until the template parameter T is known. When the compiler parses your function template T is not known and the rule to solve the ambiguity is to default to "this is not a type name".
Another short example (blatantly copied from Scott Meyers' Effective C++):
template<typename C>
void print2nd(const C& container)
{
C::const_iterator * x;
…
}
This maybe illustrates the problem a little better as it's more compact. As already said it's not clear for the parser whether C::const_iterator is a type name or a static data member as it doesn't know what C is when it parses this part of the code (it may know at a later point in time when the template is actually instantiated). So to ease the compiler implementers' lives this ambiguity is resolved to "not a type name" and if the programmer wants to use a type name which is nested inside anything that is dependent on a template parameter he/she has to use the typename keyword in front of the name to let the compiler know that it should be treated as a type name.
Unfortunately there is an exception to that rule regarding nested dependent type names when using them inside a base class list or the base class identifier in a member initialization list.
template<typename T>
struct Base {
struct Nested {
Nested(int) {}
};
};
template<typename T>
struct Derived : public Base<T>::Nested { // typename not allowed here
Derived(int i)
: Base<T>::Nested(i) // nor here
{}
};
Btw: You should set your console client's charset to UTF-8, so you get ‘*’ instead of â*â.
compiler message is a little bit misleading.
In basically signifies syntax/parsing error.
Make sure the prototype is visible in compilation file, make sure you ring buffer is declared as template. and as other people have said, check the semi-column after class declaration.