Currently, I encounter some difficulty in overloading a certain function. here's my code:
template<typename Value>
bool process(Value thisValue)
{
return processAccordingToTheType(thisValue);
}
So, there are two overloaded function of processAccordingToTheType:
bool processAccordingToTheType(int thisValue){}
bool processAccordingToTheType(string thisValue){}
when I try to compile it, it said:
error C2665: 'processAccordingToTheType' : none of the 2 overloads could convert all the argument types
what do I need to do?
Update:
int main()
{
int i = 1;
process <int> (i);
}
From your sample code I understand you need two things to be done:
Call a type specific process function
Restrict these calls to string and int types
Wrapping the processAccordingToType function inside process<T> is completely redundant: process<T> actually means 'process according to type'. The keyword here is 'template specialization'. You need to specialize your 'process according to type' method for int and string.
You can do this as below:
#include <iostream>
using namespace std;
template<typename T>
bool process(T t)
{
// call a Compile-Time Assertion
cout << "I don't want this to be called." << endl;
}
template <>
bool process<int>(int i)
{
cout << "process(int) called." << endl;
}
template <>
bool process<string>(string s)
{
cout << "process(string) called." << endl;
}
int main()
{
process(1);
process(string("s"));
process(1.0d);
}
Output:
process(int) called.
process(string) called.
I don't want this to be called.
Ideally, you want to prevent the users of your API calling process with other types. Allowing them to call and handling this at runtime (like it's done in my example) is not acceptable. You achieve this with Compile-Time Assertions. Read "Modern C++ Designs" by Andrei Alexandrescu for ways of doing that.
Look into template specialization. Does what you're looking for without deferring to another function based on type.
http://www.cprogramming.com/tutorial/template_specialization.html
You can overload function templates with either a non-template function or another template function. Make sure that whatever you do, you test incrementally as template errors are notoriously hard to understand.
http://www.cplusplus.com/doc/tutorial/templates/
#include <iostream>
using namespace std;
template <typename Value>
bool processAccordingToTheType( Value thisValue ){
cout << "Generic Type" << endl;
return false;
}
bool processAccordingToTheType(int thisValue){
cout << "int type" << endl;
return true;
}
template <typename Value>
bool process( Value thisValue ){
return processAccordingToTheType(thisValue);
}
int main( int argc, char* argv[] ){
cout << process( 1 ) << endl;
cout << process( "Hello" ) << endl;
return 0;
}
Related
Hi I am learning c++ and I read about type traits such as is_const.
is_const can be called in one line like,
cout << is_const<double>::value << endl;
I made my own version of is_const but to test if a variable is const, and it can be used like this,
#include<iostream>
using namespace std;
template<typename T>
struct check_const {
check_const(const T *x): val(std::true_type{})
{ }
check_const(T *x) : val(std::false_type{})
{ }
bool val;
};
int main()
{
const double pi= 3.14;
check_const<double> r(&pi);
cout << r.val << endl; // returns 1
double x= 2.7;
check_const<double> s(&x);
cout << s.val << endl; // returns 0
return(0);
}
I would like to call check_const in one line as well, but the compiler keeps giving me errors like
"typename not allowed"
when I try calling it like
cout << check_const<double> t(&pi)::val << endl;
How can I change check_const, so it can be called in one line?
You are just using a slightly wrong syntax here:
cout << check_const<double> t(&pi)::val << endl;
Instead use
cout << check_const<double>(&pi).val << endl;
check_const<double> t(&pi) is the syntax for the definition of a named variable, but you cannot have declarations/definitions inside an expression.
check_const<double>(&pi) is the syntax to create an unnamed temporary, which can be done in expressions.
Then you need . instead of ::, because val is a non-static member of check_const.
Starting with C++17 you could also write:
cout << check_const(&pi).val << endl;
and have the template argument be deduced for you.
All of this can be simplified though, as you aren't really using the class. You can just use the constructors as free functions:
template<typename T>
constexpr bool check_const(const T *x) noexcept { return true; }
template<typename T>
constexpr bool check_const(T *x) noexcept { return false; }
(The constexpr makes it possible to use the functions in constant expressions, but is otherwise not required. Similarly noexcept is just an indicator that the function doesn't throw exceptions, but is otherwise not required.)
This can be used more easily as
cout << check_const(&pi) << endl;
Also, instead of pointers, use references:
template<typename T>
constexpr bool check_const(const T &x) noexcept { return true; }
template<typename T>
constexpr bool check_const(T &x) noexcept { return false; }
and you can write
cout << check_const(pi) << endl;
I have a class with a template method and would like to store its specializations in a container. My question is whether it's valid to cast the specialized template method pointer to a non-template method pointer of the same class that shares the same signature. Consider:
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
struct S {
using Method = void(S::*)();
template <typename T>
void method1() {
cout << "method1(): " << T() << endl;
}
template <typename T, typename U>
void method2() {
cout << "method2(): " << T() << ", " << U() << endl;
}
void call(string name)
{
auto method_pair = methods.find(name);
if (method_pair == methods.end()) {
cout << name << " not found" << endl;
return;
}
Method& method = method_pair->second;
(this->*method)();
}
unordered_map<string, Method> methods;
};
int main()
{
S s;
s.methods["method_int"] = &S::method1<int>;
s.methods["method_bool"] = &S::method1<bool>;
s.methods["method_int_int"] = &S::method2<int, int>;
s.methods["method_bool_int"] = &S::method2<bool, int>;
cout << boolalpha;
s.call("method_int");
s.call("method_bool");
s.call("method_int_int");
s.call("method_bool_int");
s.call("nonexistant");
return 0;
}
Output:
method1(): 0
method1(): false
method2(): 0, 0
method2(): false, 0
nonexistant not found
The above code compiles and runs just fine with no warnings on my setup. I'm pretty new to C++ member function pointers and I've read that casting them can be dangerous so that's why I'm asking.
Thanks in advance.
After you instantiate a template method with distinct types it gets all the properties of a regular method: it becomes a distinct function with an address, name (that includes the types you used for instantiation), etc. So your approach is valid.
So I've found a variety of articles and posts saying that there is no way to convert typename to string but I haven't found one about the opposite. I have a template of a function with specializations:
template <typename T>
void foo(T sth) {}
template <>
void foo<int>(int sth) {}
...
and I'm reading from a file constructed like this:
int 20
double 12.492
string word
Is there a way to call the correct specialization of foo() depending on the content of the file?
Yes there is, but it requires manual code and that you know all the types that are going to appear in the file. That's because templates are compile time constructs and they cannot be instantiated at runtime.
You can always use the preprocessor or other tricks to try and reduce the boilerplate if you want to.
void callFoo(std::string type, std::any arg) {
if (type == "int")
foo<int>(std::any_cast<int>(arg));
else if (type == "double")
foo<double>(std::any_cast<double>(arg));
else if (type == "string")
foo<std::string>(std::any_cast<std::string>(arg));
}
Of course, this requires that you pass in the correct type (no implicit conversions!). I don't see any way to avoid that.
To be honest, I am not sure about understanding your question. As I interpret it, I believe that you do not need a kind of dispatcher in running time neither to compute a string containing the type name. Simply you write a general template function that calls a special template wrapper that disambiguates the call to foo() according to the type. You require that the specialized foo() receives a second special parameter (the_type<T>) which is used for disambiguating.
Here a full and operating demo:
# include <string>
# include <iostream>
using namespace std;
template<class T> struct the_type { using type = T; };
template <typename T>
void foo(const T par)
{
foo(par, the_type<T>());
}
void foo(int par, the_type<int>)
{
cout << "int " << par << endl;
}
void foo(double par, the_type<double>)
{
cout << "double " << par << endl;
}
void foo(const string & par, the_type<string>)
{
cout << "string " << par << endl;
}
void foo(const char * par, the_type<const char*>)
{
cout << "char* " << par << endl;
}
int main()
{
foo(20);
foo(12.492);
foo("word");
foo(string("word"));
}
whose output is:
int 20
double 12.492
char* word
string word
If you need another specialization, then you simply define it. In some cases, you will have to explicitly to define the specialization as the template parameter.
You could use macro manips for avoiding repetitive things. For example, given that foo() structure is the same, you could encapsulate it in a macro. Something like this:
# define GENFOO(type_name) \
void foo(type_name par, the_type<type_name>) \
{ \
cout << #type_name " " << par << endl; \
}
GENFOO(int);
GENFOO(double);
GENFOO(string)
However, I would say that each specialized version of foo() would not be so similar.
I have done a lot of research on this but I wasn't able to find a design pattern addressing the problem. This is a minimal description of what I'm trying to perform.
#include <iostream>
using namespace std;
template <class T, T default_value=T{}>
class A{
private:
T inclassValue;
public:
A(T icv):inclassValue{icv}{}
const T& operator[](int k){
if(k==1) return inclassValue;
return default_value;
}
};
struct two_int{int x;int y;};
int main(){
A<int> a{4};
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
/*
A<two_int> b{{3,5}};
cout << "b[0]=" << b[0].x << "," << b[0].y << endl;
cout << "b[1]=" << b[1].x << "," << b[1].y << endl;
*/
return 0;
}
The code will compile, link and output as expected
a[0]=0
a[1]=4
The compiler complains though and issues a warning for the line of code where default_value is used
return default_value;//Returning reference to local temporary object
which makes some sense. Uncommenting the last part in main and compiling, the compiler issue this time an error while building the template
template <class T, const T default_value= T{}>//A non-type template parameter cannot have type 'two_int'
while what I ideally hope for is
b[0]=0,0
b[1]=3,5
I was able to come up with a solution by adding an extra helper class, that will provide the default_value of T (as a static member), to the template arguments. I'm not convinced by the robustness of my trick and I was wondering if there exists a design pattern addressing this. The warning for types and the error for non-types. Also, I shall add that my primary goal is to be able to provide default_value at will (6 for int for example instead of 0).
Thanks
Not exactly sure what you're looking for, but perhaps a static helper finishing for creating a static default T could be useful:
template <typename T>
static const T& default_value() {
static const T* t = new T{};
return *t;
}
Note this will construct T at most once even across threads (in c++11), but still never destruct T. Since it's static, it's likely the lack of destruction is acceptable, but this of course depends on T.
Here is one version that forwards arguments to the constructor of a default_value stored as constexpr. You are quite limited here as to what is valid to pass as arguments (not sure exactly how limited) so it will depend on your use-case.
#include <iostream>
using namespace std;
template <class T, auto... Args>
class A{
private:
T inclassValue;
constexpr static T default_val = T{Args...}; // Changed to curly brackets here
public:
constexpr A(T icv):inclassValue{icv}{}
const T& operator[](int k){
if(k==1) return inclassValue;
return default_val;
}
};
struct two_int{int x;int y;};
int main(){
A<int> a{4};
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
A<two_int> b{{3,5}};
cout << "b[0]=" << b[0].x << "," << b[0].y << endl;
cout << "b[1]=" << b[1].x << "," << b[1].y << endl;
return 0;
}
I am trying to implement a template function which takes std::string as input parameter and will do some logic and returns template value. I do not know whether its possible or not because while calling this function there is no information abut the template type and its showing **No matching member function for call to 'functionName'. I am using following code to do this and getting the same. Any suggestions is, there any way to do this.
#include <iostream>
using namespace std;
class Test{
public:
template <class DefaultType>
DefaultType GetDefaultValueType(std::string type);
};
template <class DefaultType>
DefaultType Test::GetDefaultValueType(std::string type)
{
DefaultType temp;
if (type == "Test") {
temp = type;
return temp;
}
else if(10 == atoi(type.c_str()))
{
temp = 1;
return temp;
}
return temp;
}
int main(void){
Test intAccount;
cout << "Current balance: " << intAccount.GetDefaultValueType("Test") << endl; //No matching member function for call to 'GetDefaultValueType'
cout << "Current balance: " << intAccount.GetDefaultValueType("10") << endl; ////No matching member function for call to 'GetDefaultValueType'
return 0;
}
If the compiler is unable to deduce the type of the template you have to provide it. You can call the function as
intAccount.GetDefaultValueType<type_to_conver_to>("some_value");
You could instead return void and pass the template parameter as a reference:
template <class DefaultType>
void Test::GetDefaultValueType(std::string type, DefaultType& output)
{
if (type == "Test")
{
output = 1;
}
else if (10 == atoi(type.c_str()))
{
output = 0;
}
}
Looking at cppreference, "Every template is parametrized by one or more template parameters". Each of those template parameters allows the compiler to, essentially, create a copy of the template function for every parameter combination it finds in the rest of your code. The compiler therefore won't know what
intAccount.GetDefaultValueType("Test")
will return unless you specify it. In your case, you'd need the following:
intAccount.GetDefaultValueType<int>("Test")