Argument list for class template `sgl::Bag` is missing - c++

So I am currently working on a project to make a library with all of the different data structures in C++. Here I have declared a class Bag:
template<typename Type>
class Bag
{
// ...
inline static const char* print_seperator = "\n";
public:
// ...
inline static void set_seperator(const char* new_seperator)
{
Bag::print_seperator = new_seperator;
}
}
Now this works fine, but when I try to use it in my main() function like this:
sgl::Bag::set_seperator(", ");
This shows the following error:
Argument list for class template sgl::Bag is missing
..so I gave the argument list for the class template:
sgl::Bag<int>::set_seperator(", ");
..and it works fine.
But I don't want to type that out every time. Is there any way I can overcome this?

You can use default template argument for the template type parameter Type as shown below:
//use default argument for template type parameter "Type"
template<typename Type = int>
class Bag
{
// ...
inline static const char* print_seperator = "\n";
public:
// ...
inline static void set_seperator(const char* new_seperator)
{
Bag::print_seperator = new_seperator;
}
};
int main()
{
//no need to specify int
Bag<>::set_seperator(", "); //angle bracket still needed
return 0;
}
Demo

Related

Deduce the correct specialized member method of a class to match the data type of variable it is assigned to

I have a class that reads a script and stores variables and their respective types which I reference by name (string). The class has a templatized member method named get, which fetches the variable that matches the name parameter from one of the member tables, and needs to return data of the same type as the variable type it is assigned to. To better illustrate my question, suppose I have a simplified class such as:
class Script
{
public:
template <typename T>
T get(std::string name);
private:
//data stored in associative containers such as:
// std::map<std::string, int> int_data;
// std::map<std::string, bool> bool_data;
};
In the implementation file, the member method is specialized:
template <>
int Script::get(std::string name)
{
int value = retrieve_integer(name);
return value;
}
template <>
bool Script::get(std::string name)
{
bool value = retrieve_boolean(name);
return value;
}
I would like to call the class method like this without explicitly providing the type with script.get<int>("varName"):
Script script; // loads script and reads data
bool useVsync = script.get("useVsync"); // calls the bool specific get
int screenWidth = script.get("screenWidth"); // calls the int specific get
How would I do this without causing could not deduce template parameter T errors? I know that this should be possible, because I have used libraries that allowed such syntax.
As explained in comment, you may abuse of conversion operator:
class Script
{
public:
struct ValueProxy {
operator bool() const {
return script.bool_data[name];
}
operator int() const {
return script.int_data[name];
}
ValueProxy& operator= (bool b) {script.bool_data[name] = b;}
ValueProxy& operator= (int n) {script.int_data[name] = n;}
Script &script;
std::string name;
};
ValueProxy get(std::string name) {
return ValueProxy{*this, std::move(name)};
}
private:
//data stored in associative containers such as:
std::map<std::string, int> int_data;
std::map<std::string, bool> bool_data;
};
int main() {
Script script;
script.get("myBool") = true;
script.get("MyInt") = 42;
bool b = script.get("MyBool"); // true
int i = script.get("MyInt"); // 42
int j = script.get("MyBool"); // 0
}

Accessing a class template parameter type inside a member function with a lambda fails

I have a class template with a member function that has a lambda which wants to use a class template parameter type. It fails to compile inside the lambda but succeeds, as anticipated, outside the lambda.
struct wcout_reporter
{
static void report(const std::wstring& output)
{
std::wcout << output << std::endl;
}
};
template <typename reporter = wcout_reporter>
class agency
{
public:
void report_all()
{
reporter::report(L"dummy"); // Compiles.
std::for_each(reports_.begin(), reports_.end(), [this](const std::wstring& r)
{
reporter::report(r); // Fails to compile.
});
}
private:
std::vector<std::wstring> reports_;
};
int wmain(int /*argc*/, wchar_t* /*argv*/[])
{
agency<>().report_all();
return 0;
}
The compilation error:
error C2653: 'reporter' : is not a class or namespace name
Why can't I access the class template parameter type inside the member function lambda?
What do I need to do to gain access to the class template parameter type inside the member function lambda?
This should compile OK as-is. It appears that your compiler has a bug in the name lookup rules in a lambda. You could try adding a typedef for reporter inside report_all.
Use typedef:
template <typename reporter = wcout_reporter>
class agency
{
typedef reporter _myreporter;
public:
void report_all()
{
reporter::report(L"dummy"); // Compiles.
std::for_each(reports_.begin(), reports_.end(), [this](const std::wstring& r)
{
// Take it
agency<>::_myreporter::report(r);
});
}
};

How to make this specialized function work

Here's the deal. I've looked on this forum and I didn't find the information I'm searching for or I'm probably not able to repeat it for my problem. I have a class Table which is generic and I have a class named MyString.
template <typename typeGen, int DIM>
class Table {
public:
TableauGenerique() : index_(0) { //On initialise courant à 0
}
void add(typeGen type);
private:
typeGen tableGen_[DIM];
int index_;
};
My problem is with the add function.
I sometimes have to do this in the main.cpp: (which works well)
Table <float,6> tabFloat;
tabFloat.add(1.6564);
and at one point, I need to do this which doesn't work because I need to specialize the add function to create an object of MyString, to pass it the string and then store the object in the array (tableGen) :
TableauGenerique <MyString,4> tabString;
So I tried this (after the class), without success.
template <typename typeGen, int DIM>
void Table<typeGen,DIM>::add(typeGen type){ //Which is the generic one for float or ints
if(index_ < DIM) {
tableGen_[courant_] = type;
index_++;
}
}
template <class typeGen, int DIM>
void Table<typeGen,DIM>::add<string>(typeGen type) { //(line 75) Which is the specific or specialized function for myString
MyString str(type);
if(index_ < DIM) {
tableGen_[courant_] = str;
index_++;
}
}
So, How can I make this work because it doesn't compile at all, saying: line75 : error: expected initializer before '<' token and in the main it says not matching function to call Table::add(const char[6]),
I hope everything is clear enough. Let me know if somethings is unclear.
Thank you very much for your help !
template <class typeGen, int DIM>
void Table<typeGen,DIM>::add<string>(typeGen type)
You're trying to specialize add() when in fact it is not a function template to begin with. How do you expect it to work?
You probably meant: (specialization of the class)
template <int DIM>
void Table<string,DIM>::add(string type)
But then this is allowed only if you specialize the class itself. Without specializing the class, the above code would give compilation error!
EDIT:
You can read these online tutorials:
Introduction to C++ Templates
14.5 — Class template specialization
Template Specialization and Partial Template Specialization
Explicit specialization (C++ only)
If you can control the code of the MyString class, you can provide constructors that act as implicit conversions from float to MyString. An example:
#include <string>
#include <sstream>
#include <iostream>
class MyString {
public:
MyString(float number) {
std::stringstream buffer;
buffer << number;
value = buffer.str();
}
void print() {
std::cout << value << std::endl;
}
private:
std::string value;
};
template <class T>
class Foo {
public:
void DoStuff(T item) {
item.print();
}
};
int main() {
Foo<MyString> foo;
foo.DoStuff(1.342); // implicitly converts float to MyString
return 0;
}
This way, you do not need any specialization of the add method. However, implicit conversions are tricky, and you have be careful not to invoke them accidentally, and they may create ambiguities.
EDIT: Upon a second thought, my suggestion below is basically equivalent to
Table<MyString,4> tabString;
tabString.add(MyString("whatever"));
and therefore excessive and/or does not solve the problem. Feel free to ignore :)
I would extend the class Table with a generic method to add something from which you can construct an object of the desired type:
template <typename typeGen, int DIM>
class Table {
public:
Table() : index_(0) {}
void add(typeGen type);
// The additional method
template<typename T> void add(const T& src);
private:
typeGen tableGen_[DIM];
int index_;
};
template<typename typeGen, int DIM>
template<typename T>
void Table<typeGen,DIM>::add(const T& src) {
if(index_ < DIM) {
tableGen_[courant_] = typeGen(src);
index_++;
}
}
Note construction of a temporary typeGen object before the assignment.
Assuming that MyString object can be constructed from a string literal, i.e. from const char*, you can then use it as following:
Table<MyString,4> tabString;
tabString.add("whatever");
or if the above assumption is wrong, the following should probably work (because you constructed a MyString instance from a string instance):
tabString.add(string("whatever"));

default template arguments in c++

Suppose i have a function template StrCompare
template<typename T=NonCaseSenCompare>//NonCaseSenCompare is a user defined class look at the detailed code below.
int StrCompare(char* str1, char* str2)
{
...
}
now in the main function i write a line
char* str1="Zia";
char* str2="zia";
int result=StrCompare(str1,str2);
it should work because we have provided a default template argument, but it does'nt compiler gives the following error
no matching function for call to `StrCompare(char*&, char*&)'
Now the detailed code is given by
#include<iostream.h>
class CaseSenCompare
{
public:
static int isEqual(char x, char y)
{
return x==y;
}
};
class NonCaseSenCompare
{
public:
static int isEqual(char x,char y)
{
char char1=toupper(x);
char char2=toupper(y);
return char1==char2;
}
};
template<typename T=NonCaseSenCompare>
int StrCompare(char* str1, char* str2)
{
for(int i=0;i < strlen(str1)&& strlen(str2);i++)
{
if(!T::isEqual(str1[i],str2[i]))
return str1[i]-str2[i];
}
return strlen(str1)-strlen(str2);
}
main()
{
char* ptr1="Zia ur Rahman";
char* ptr2="zia ur Rahman";
int result=StrCompare(ptr1,ptr2);//compiler gives error on this line
cout<<result<<endl;
system("pause");
}
If I write
int result=StrCompare<>(ptr1,ptr2);
compiler gives the same error message.
As gf and AndreyT already wrote, you can't have default template arguments with function templates. However, if you turn your comparators into function objects, you can still use default function arguments:
template<typename Comp>
int StrCompare(char* str1, char* str2, Comp = NonCaseSenCompare())
{
...
}
You can now call StrCompare() like this
StrCompare("abc","aBc",CaseSenCompare());
or like this:
StrCompare("abc","aBc"); // uses NonCaseSenCompare
A comparator would then have to look like this:
struct CaseSenCompare {
bool operator()(char x, char y) const {return x==y;}
};
Adjust StrCompare() accordingly.
§14.1/9:
A default template-argument shall not
be specified in a function template
declaration or a function template
definition, nor in the
template-parameter-list of the
definition of a member of a class
template.
A simple work-around would be to move it into a class:
template<typename T=NonCaseSenCompare>
struct StrCompare {
static int compare(char* str1, char* str2) { /* ... */ }
};
Firstly, function templates do not support default template arguments, only class templates do.
Secondly, even when all class template parameters have default arguments, you still have to specify an empty <> to refer to that class template.
What i use is next trick;
lets say you want to have function like this
template <typename E, typename ARR_E = MyArray_t<E> > void doStuff(ARR_E array)
{
E one(1);
array.add( one );
}
you will not be allowed, but i do next way:
template <typename E, typename ARR_E = MyArray_t<E> >
class worker {
public:
/*static - as you wish */ ARR_E* parr_;
void doStuff(); /* do not make this one static also, MSVC complains */
};
template <typename E, typename ARR_E>
void worker::doStuff<E, ARR_E>::getChunks()
{
E one(1);
parr_->add( one );
}
so this way you may use it like this.
MyArray_t my_array;
worker<int> w;
w.parr_ = &arr;
w.doStuff();
as we can see no need to explicitly set second parameter.
maybe it will be useful for someone.

Best way to for C++ types to self register in a list?

Suppose I have some per-class data: (AandB.h)
class A
{
public:
static Persister* getPersister();
}
class B
{
public:
static Persister* getPersister();
}
... and lots and lots more classes. And I want to do something like:
persistenceSystem::registerPersistableType( A::getPersister() );
persistenceSystem::registerPersistableType( B::getPersister() );
...
persistenceSystem::registerPersistableType( Z::getPersister() );
... for each class.
My question is: is there a way to automate building a list of per-type data so that I don't have to enumerate each type in a big chunk (as in the above example)?
For example, one way you might do this is: (AutoRegister.h)
struct AutoRegisterBase
{
virtual ~AutoRegisterBase() {}
virtual void registerPersist() = 0;
static AutoRegisterBase*& getHead()
{
static AutoRegisterBase* head= NULL;
return head;
}
AutoRegisterBase* next;
};
template <typename T>
struct AutoRegister : public AutoRegisterBase
{
AutoRegister() { next = getHead(); getHead() = this; }
virtual void registerPersist()
{
persistenceSystem::registerPersistableType( T::getPersister() );
}
};
and use this as follows: (AandB.cxx: )
static AutoRegister<A> auto_a;
static AutoRegister<B> auto_b;
Now, after my program starts, I can safely do: (main.cxx)
int main( int, char ** )
{
AutoRegisterBase* p = getHead();
while ( p )
{
p->registerPersist();
p = p->next;
}
...
}
to collect each piece of per-type data and register them all in a big list somewhere for devious later uses.
The problem with this approach is that requires me to add an AutoRegister object somewhere per type. (i.e. its not very automatic and is easy to forget to do). And what about template classes? What I'd really like is for the instantiation of a template class to somehow cause that class to get automatically registered in the list. If I could do this I would avoid having to have the user of the class (rather than the author) to remember to create a:
static AutoRegister< SomeClass<X1> > auto_X1;
static AutoRegister< SomeClass<X2> > auto_X2;
...
etc....
for each template class instantiation.
For FIW, I suspect there's no solution to this.
You can execute something before main once if a instantiation of a template is made. The trick is to put a static data member into a class template, and reference that from outside. The side effect that static data member triggers can be used to call the register function:
template<typename D>
struct automatic_register {
private:
struct exec_register {
exec_register() {
persistenceSystem::registerPersistableType(
D::getPersister()
);
}
};
// will force instantiation of definition of static member
template<exec_register&> struct ref_it { };
static exec_register register_object;
static ref_it<register_object> referrer;
};
template<typename D> typename automatic_register<D>::exec_register
automatic_register<D>::register_object;
Derive the class you want to be auto-registered from automatic_register<YourClass> . The register function will be called before main, when the declaration of referrer is instantiated (which happens when that class is derived from, which will implicitly instantiate that class from the template).
Having some test program (instead of the register function, a function do_it is called):
struct foo : automatic_register<foo> {
static void do_it() {
std::cout << " doit ";
}
};
int main() {
std::cout << " main ";
}
Yields this output (as expected):
doit main
Register each template at run-time in the constructor. Use a static variable per template to check if the type has already been registered. The following is a quickly hacked together example:
#include <iostream>
#include <vector>
using namespace std;
class Registerable {
static vector<Registerable *> registry_;
public:
static void registerFoo(Registerable *p)
{
registry_.push_back(p);
}
static void printAll()
{
for (vector<Registerable *>::iterator it = registry_.begin();
it != registry_.end(); ++it)
(*it)->print();
}
virtual void print() = 0;
};
vector<Registerable *> Registerable::registry_;
template <typename T>
class Foo : public Registerable {
static bool registered_;
public:
Foo()
{
if (!registered_) {
registerFoo(this);
registered_ = true;
}
}
void print()
{
cout << sizeof (T) << endl;
}
};
template <typename T> bool Foo<T>::registered_ = false;
int
main(int argc, char *argv[])
{
Foo<char> fooChar;
Foo<short> fooShort;
Foo<int> fooInt;
Registerable::printAll();
return 0;
}
It should output the size of each template parameter in the order the classes were instantiated:
1
2
4
This version removes the registration code from each constructor and puts it in a base class.
#include <iostream>
#include <vector>
using namespace std;
class Registerable {
static vector<Registerable *> registry_;
public:
static void registerFoo(Registerable *p)
{
registry_.push_back(p);
}
static void printAll()
{
for (vector<Registerable *>::iterator it = registry_.begin();
it != registry_.end(); ++it)
(*it)->print();
}
virtual void print() = 0;
};
vector<Registerable *> Registerable::registry_;
template <typename T>
class Registerer : public Registerable {
static bool registered_;
public:
Registerer(T *self)
{
if (!registered_) {
registerFoo(self);
registered_ = true;
}
}
};
template <typename T> bool Registerer<T>::registered_ = false;
template <typename T>
class Foo : public Registerer<Foo<T> > {
public:
Foo() : Registerer<Foo<T> >(this) { }
void print()
{
cout << sizeof (T) << endl;
}
};
int
main(int argc, char *argv[])
{
Foo<char> fooChar;
Foo<short> fooShort;
Foo<int> fooInt;
Registerable::printAll();
return 0;
}
I added an example of another non-template class using the registry. So, the final output would be:
foo: 1
foo: 2
foo: 4
bar
The Registerable solution is a neat idea, but has a couple of issues.
Ideally, I'd like to not add code to the constructor:
Because it relies on calling the constructor in order to register the type, it's a
little haphazard about what gets registered and what doesn't.
For things like persistence, I may never call the constructor of a particular type
before using the list, but I may need the type's data in the list in order to
know how to un-persist an object in a file.
There's runtime cost during the constructor call. I'd like to front load the time cost
and not pay the cost many times. If I had a vector of these objects and resized the
vector I'd pay the time-cost each time the copy constructor was called.
Use file-level static blocks to perform the different registrations
A static block? What's that?
A static block is a block of code (i.e. code between curly braces, which defines a scope) that gets executed sometime before main() runs. Java has this feature, and C++ has it too-
Whatch'a talkin' bout, Willis? C++ don't have no static blocks!
No, really, C++ has static blocks. You just need to, uh, shall we say, "expose" their existence.
Hmm. Curious. And how do the static blocks help my registration problem?
It's really very simple. Right after you define class A, you register it like so:
class A { /* ... whatever ... */ };
static_block {
persistenceSystem::registerPersistableType(A::getPersister());
}
There is one caveat, though: static blocks can be a part of the static initialization order fiasco together with any statically-initialized part of your persistence system; so you need to make sure it's ok for these static blocks to run before (most) other statics; and that it's ok for the different classes' Persister's to be registered in arbitrary order.