I got following code running
using namespace std;
#include <iostream>
template<typename a> struct function
{
void self1(){ cout << "hello world 1111" << endl; }
};
template<typename a> struct function<a&>
{
void self2() { cout << "hello world 2222" << endl; }
};
int main()
{
function<int> a;
a.self1();
function<int&> b;
b.self2();
return 0;
}
The result is:
hellow world 1111
heloow world 2222
Would like to ask the relation ship between the first "struct function" and the second "struct function"
Is the second one classfied as "template specialization" for the first one? (seems not)
I can see that the 2nd one is based on the 1st one. (By removing the 1st one, it is not compilable). But
b.self1() is not defined.
So somehow the 2nd have redefined the struct to a new one?
I can see that the 2nd one is based on the 1st one. (By removing the
1st one, it is not compilable). But
b.self1() is not defined. So somehow the 2nd have redefined the struct
to a new one?
function is a struct template, it's not a struct by itself. At the moment of instantiating one like you did : function<int> a; the compiler generates a struct function_int that contains int for all T's (or a's in this case).
template<typename a> struct function<a&>
This is a specialisation of the struct template that's used for when a is a reference type. This specialisation can't use any members/methods of the "original" struct template.
Related
I'm wondering how exactly this code works in detail (e.g. how is it able to directly access the value of TYPE).
I saw this code in a larger codebase (which is non-public, so the example is paraphrased). I've never seen this specific use-case. Is passing a template parameter like this common? Does it have a specific name/is this an idiom/pattern? When would you use this and why?
#include <iostream>
namespace FileA
{
struct Foo
{
enum TYPE
{
ENTRY,
};
void callme()
{
std::cout << "Foo\n";
}
};
}
namespace FileB
{
template <typename T>
void fun(T& obj)
{
std::cout << T::ENTRY << "\n";
obj.callme();
}
}
int main()
{
FileA::Foo f;
FileB::fun(f);
}
This will print:
0
Foo
a template is a kind of macro in the general sense of the term, so if you "expand" FileB::fun(f); T is replaced by the type of f being FileA::Foo and it is like if you have :
void fun(FileA::Foo& obj)
{
std::cout << FileA::Foo::ENTRY << "\n";
obj.callme();
}
because FileA::Foo::ENTRY is 0 the std::cout writes 0, then you apply FileA::Foo::callme() whose prints Foo
Warning, a template is much more than that, it is just a very simplified explanation of how that example works and produces the outputs, do not take it literally please ^^
Is it possible to recognize all calling of a certain function in everywhere
function1<T1>(); function1<T4>(); ...
then add a line that calling this following line in a certain place?
function2<T1>(); function2<T4>(); ...
For example,
class X{
template <class T> function1(){ }
template <class T> function2(){ }
}
class A{}
class B{}
class C{}
int main(){
X x;
//vvvv this code (hopefully) will be auto generated (by macro?)
x.function2<A>();
x.function2<B>(); //<--- I don't care about order of A or B
//x.function2<C>(); //<--- this line should not be generated
//^^^^ Only X's function1 should be recognized,
// not other class's functions with the same name.
x.function1<B>();
x.function1<A>();
x.function1<B>(); .... // called in various places in many .cpp
//If it is called in another .cpp, but not here, it should still be recognized
}
Edit
My old code call :-
function2<T>() inside function1<T>()
It costs CPU significantly (I profiled), because function1 have to check whether function2 was called or not every time.
Here is a draft of a near-zero overhead solution that will work only if you are not going to invoke function1() before main():
#include <iostream>
#include <typeinfo>
template <class T>
void function2()
{
std::cout << "function2<" << typeid(T).name() << ">()" << std::endl;
}
bool dummy = true;
template <class T>
struct Func1WasInstantiated
{
struct CallFunc2
{
CallFunc2() { function2<T>(); }
void operator()() const { dummy = false; }
};
static CallFunc2 callFunc2;
};
template <class T>
typename Func1WasInstantiated<T>::CallFunc2 Func1WasInstantiated<T>::callFunc2;
template <class T>
void function1()
{
Func1WasInstantiated<T>::callFunc2();
std::cout << "function1<" << typeid(T).name() << ">()" << std::endl;
}
int main()
{
std::cout << "------- Entered main() ---------" << std::endl;
function1<int>();
function1<double>();
function1<int>();
return 0;
}
Output (check it on IDEONE):
function2<i>()
function2<d>()
------- Entered main() ---------
function1<i>()
function1<d>()
function1<i>()
The global variable dummy is the acceptor of the side effect, that ensures that Func1WasInstantiated<T>::callFunc2 is linked into the program and makes the code work as intended. Without the side effect contained in callFunc2() I can imagine an aggressively optimizing compiler eliminating that line from function1() (that is normal) and letting the linker leave out the callFunc2 objects as they become unreferenced (I cannot judge whether this would be against the C++ standard or not).
Consider the following code:
#include <iostream>
#include <cstdlib>
#include <ctime>
struct BaseClass {
static int identifier() {
static int identifier_counter = 0;
return identifier_counter++;
}
};
template <class D>
struct Class: public BaseClass {
static int identifier() {
static int class_identifier = BaseClass::identifier();
return class_identifier;
}
};
struct A: public Class<A> { };
struct B: public Class<B> { };
int main() {
std::srand(std::time(0));
int r = std::rand()%2;
if(r) {
std::cout << "A: " << A::identifier() << std::endl;
std::cout << "B: " << B::identifier() << std::endl;
} else {
std::cout << "B: " << B::identifier() << std::endl;
std::cout << "A: " << A::identifier() << std::endl;
}
}
It's a reduced, but still plausible representation of the problem.
Any derived class will have a specific, different identifier on runtime and two instances of the same type will share the same identifier. Surely a good solution for such a problem.
Unfortunately, those identifiers depend on the order on which the identifier members are invoked (we can see it easily by running multiple times the example). In other words, given two classes A and B, if it happens that running twice the software their identifier members are invoked in different order, they have different identifiers.
My problem is that, for some reasons, I need to store those identifiers somewhere and let them survive the single execution, so that I can reason on the original types once the application runs once more and decide to read those values from the storage.
An alternative would be to use hash_code from type_info, but it suffers from other problems. Another solution would be to force the calls to the identifier members during the bootstrap of the application, but this one also has several drawbacks.
I'd like to know if there is so far an easy to implement though still elegant solution that is completely transparent to the developer to identify types over several executions, as the one above is for the single run of the application.
The problem of having unique persistent identifier for every class is unsolvable with C++. Sorry. You will either depend on the order of calling your initializaer functions, or, if you call them from initializers of static objects, on the order of static initializer (which will usually depend on the order of your object files in your link line).
And of course, there is no guarantee that hash will be unique.
You will have to use external script for this. In particular, something like this might be used:
// when class is first created
class Foo {
static int class_id = ?CLASS_ID?;
};
// after class is process by the script
class Foo {
static int class_id = 123; // Autogenerated by 'stamp_id.pl'
};
You might have a perl script running as part of the compilation (the very first thing) which opens all .h files in the project directory, reads all of them, counts all instances of Autogenerated by 'stamp_id.pl' and than stamps all ?CLASS_ID? with incremented counter (starting from the number of already generated ids). To add some safety, you might want a better pattern than simple ?...?, but I think, you got the idea.
Even if they are slightly different as questions, here I proposed a solution that maybe can fit well also with this question.
It isn't based on the CRTP idiom and it has the advantage of being a non-intrusive solution.
It follows a minimal, working example:
#include<cstddef>
#include<functional>
#include<iostream>
template<typename T>
struct wrapper {
using type = T;
constexpr wrapper(std::size_t N): N{N} {}
const std::size_t N;
};
template<typename... T>
struct identifier: wrapper<T>... {
template<std::size_t... I>
constexpr identifier(std::index_sequence<I...>): wrapper<T>{I}... {}
template<typename U>
constexpr std::size_t get() const { return wrapper<U>::N; }
};
template<typename... T>
constexpr identifier<T...> ID = identifier<T...>{std::make_index_sequence<sizeof...(T)>{}};
// ---
struct A {};
struct B {};
constexpr auto id = ID<A, B>;
int main() {
switch(id.get<B>()) {
case id.get<A>():
std::cout << "A" << std::endl;
break;
case id.get<B>():
std::cout << "B" << std::endl;
break;
}
}
The main problem is that the ids can change if an element is removed from the types list.
Anyway, it's trivial to define an empty placeholder to work around the issue.
I have a quick question about item 48 in Scott Meyers' "Effective C++".
I just don't understand the code copied from the book below,
#include <iostream>
using namespace std;
template <unsigned n>
struct Factorial
{
enum { value=n*Factorial<n-1>::value };
};
template <>
struct Factorial<0>
{
enum { value=1};
};
int main()
{
cout<<Factorial<5>::value<<endl;
cout<<Factorial<10>::value<<endl;
}
Why do I have to use enum in template programming?
Is there an alternative way to do this?
Thanks for the help in advance.
You could use static const int also:
template <unsigned n>
struct Factorial
{
static const int value= n * Factorial<n-1>::value;
};
template <>
struct Factorial<0>
{
static const int value= 1;
};
This should be fine also. The result is same in both cases.
Or you could use existing class template, such as std::integral_constant (in C++11 only) as:
template <unsigned n>
struct Factorial : std::integral_constant<int,n * Factorial<n-1>::value> {};
template <>
struct Factorial<0> : std::integral_constant<int,1> {};
I see that the other answers cover the alternative approaches well, but no one's explained why the enum (or static const int) is required.
First, consider the following non-template equivalent:
#include <iostream>
int Factorial(int n)
{
if (n == 0)
return 1;
else
return n * Factorial(n-1);
}
int main()
{
std::cout << Factorial(5) << std::endl;
std::cout << Factorial(10) << std::endl;
}
You should be able to understand it easily. However, it's disadvantage is that the value of the factorial will be computed at run-time, i.e. after running your program the compiler will execute the recursive function calls and calculations.
The idea of template approach is to perform the same calculations at compile-time, and place the result in the resulting executable. In other words, the example you presented resolves to something alike:
int main()
{
std::cout << 120 << std::endl;
std::cout << 3628800 << std::endl;
}
But in order to achieve that, you have to 'trick' the compiler into performing the computations. And in order to do that, you need to let it store the result somewhere.
The enum is there exactly in order to do that. I will try to explain that by pointing out what would not work there.
If you tried to use a regular int, it would not work because a non-static member like int is meaningful only in a instantiated object. And you can't assign a value to it like this but instead do that in a constructor. A plain int won't work.
You need something that would be accessible on an uninstantiated class instead. You could try static int but it still doesn't work. clang would give you a pretty straightforward description of the problem:
c.cxx:6:14: error: non-const static data member must be initialized out of line
static int value=n*Factorial<n-1>::value ;
^ ~~~~~~~~~~~~~~~~~~~~~~~
If you actually put those definitions out-of-line, the code will compile but it will result in two 0s. That is because this form delays the computation of values to the initialization of program, and it does not guarantee the correct order. It is likely that a Factorial<n-1>::values was obtained before being computed, and thus 0 was returned. Additionally, it is still not what we actually want.
Finally, if you put static const int there, it will work as expected. That's because static const has to be computed at the compile time, and that's exactly what we want. Let's type the code again:
#include <iostream>
template <unsigned n>
struct Factorial
{
static const int value=n*Factorial<n-1>::value ;
};
template <>
struct Factorial<0>
{
static const int value=1;
};
int main()
{
std::cout << Factorial<5>::value << std::endl;
std::cout << Factorial<10>::value << std::endl;
}
First you instantiate Factorial<5>; static const int forces the compiler has to compute its value at compiler time. Effectively, it instantiates the type Factorial<4> when it has to compute another value. And this goes one until it hit Factorial<0> where the value can be computed without further instantiations.
So, that was the alternate way and the explanation. I hope it was at least a bit helpful in understanding the code.
You can think of that kind of templates as a replacement of the recursive function I posted at the beginning. You just replace:
return x; with static const int value = ...,
f(x-1) with t<x-1>::value,
and if (n == 0) with the specialization struct Factorial<0>.
And for the enum itself, as it was already pointed out, it was used in the example to enforce the same behavior as static const int. It is like that because all the enum values need to be known at compile-time, so effectively every requested value has to be computed at compile-time.
To be more specific, the "enum hack" exists because the more correct way of doing it with static const int was not supported by many compilers of the time. It's redundant in modern compilers.
You can use static const int as Nawaz says. I guess the reason Scott Myers uses an enum is that compiler support for in-class initialization of static const integers was a bit limited when he wrote the book. So an enum was a safer option.
You can use an int instead of static const it for this as follows:
template<int n>
struct Factorial
{
int val{ n*Factorial<n - 1>().val };
};
template<>
struct Factorial<0>
{
int val{1};
};
int main()
{
cout << "Factorial 5: " << Factorial<5>().val << endl;
}
You can also use function template instead of struct/class template:
template<int n>
int fact()
{
return n*fact<n - 1>();
}
template <>
int fact<0>()
{
return 1;
}
int main()
{
cout << "Fact 5: " << fact<5>() << endl;
}
This is what I want to do:
enum MyEnum
{
ONE = 1, TWO, THREE
};
template<class T>
void func()
{
cout << T::TWO << endl;
}
int main()
{
func<MyEnum>();
};
It works, but I get a warning: "warning C4482: nonstandard extension used: enum 'MyEnum' used in qualified name"
How can I do this without getting the warning
Enum is a little tricky here. The type ONE and TWO will be in the outer namespace.
So adding the type to the name results in the warning.
You could just remove the qualifier
template<class T>
void func()
{
cout << TWO << endl;
}
Since the TWO is known in the outer namespace.
You could also just move your enum to some sort of enclosing struct.
struct EnumContainer
{
enum MyEnum
{
ONE = 1, TWO, THREE
};
};
template<class T>
void func()
{
std::cout << T::TWO << std::endl;
}
int main()
{
func<EnumContainer>();
};
Now the compiler should be fine.
Enums (pre C++0x) are treated like integral types.
In fact, the notation MyEnum::TWO is garbage: there is no class or namespace MyEnum. The names ONE, TWO, and THREE are brought into the namespace where the enum is defined [in this case, the global namespace].
You should get an error like TWO is not a member of MyEnum.
One way to emulate the behavior is to put it in a struct or class, like others have suggested.
While it would be nice to use the enum as the template parameter and have it recognize each individual enum separately as you've written it, it won't happen. Instead, may I suggest that you declare the following:
template<MyEnum T>
void func(){
std::cout << T << std::endl;
}
The great thing about C++ is that the way templates are structured gives you a Turning complete system. Hence, you don't need a separate call like this, as you've declared to get each individual enum value. You can create a separate function for each value when you need it and only when you need it.
Now, getting to the other problem of your question, as #delnan commented, you can't have two different Enums with the same name. You can, however, have a class with a member variable called TWO such that:
struct Foo{
int TWO;
};
struct Bar{
int TWO;
};
template<typename T>
void func(){
std::cout << T::TWO << std::endl;
}
Hope that helps.