Jump to content
  • Advertisement
MarcusAseth

Questions about Templates

This topic is 403 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was doing an experiment, code below:

template<typename T>
struct S
{
	explicit S(T v) :val{ v } {};
	T val;
};

int main()
{
	S<int> MyS('g');
	cout << MyS.val << endl;//Output is 103

	return 0;
}

Even though I am providing T with a type which is int, and I have an explicit constructor, why I have an implicit conversion from char to int? Shouldn't it see that T is int since I'm telling it so and thus give me error for constructing an S out of char? :S

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
Advertisement

The explicit keyword means that it won't create an instance of the object without you explicitly constructing one - for example, as part of an expression where it might normally make sense to the compiler to cast some object to this type, but where you want to disallow this.

Here, you do explicitly construct an object of the type, so it calls the constructor, and it makes the normal effort to convert the argument for you.

In this example, it's the 'int' that has an 'implicit' or 'converting' constructor, which magically creates an int out of a char. You don't get to change the semantics of ints, though.

To recap: explicit constructors don't say anything about their arguments, they say things about when they can be legitimately called.

Share this post


Link to post
Share on other sites

Not grossly. You obviously understand the basic concept, of avoiding the implicit conversion, but you were just unsure which 'end' of the process it applied to. :)

Share this post


Link to post
Share on other sites

I'm changing the title of the topic into "Questions about Templates" because I'm experimenting with it and I know I will have more than one, doesn't seems right to make 1000 mini-topics :/

So now I have the code below:

template<typename T>
struct S
{
	S(T v) :val{ v } {};
	T val;
};

template <typename R, typename T>
R& get(T& e)
{
	return e.val;
}

int main()
{
	S<char> MySChar('B');
	cout << "MySChar: " << MySChar.val << endl;
	
	cout << "Returned val: " << get<char>(MySChar) << endl;

	return 0;
}

The function get is not part of the S class, as required from the book exercise (which is "" Add a function template get() that returns a reference to val.")

I don't like that I have to specify the return type when I call it, if I have 5 different instantiation of S it becomes messy, so I was trying to make it in such a way that I can just write get(MySChar) and it just works with wathever instantiation of S, but I am failing on it, code below:

template<typename T>
struct S
{
	S(T v) :val{ v } {};
	T val;
	typedef T type;
};

template <typename T, typename R>
R& get(T& e)
{
	using R = e.type;
	return e.val;
}

int main()
{
	S<char> MySChar('B');

	cout << "MySChar: " << MySChar.val << endl;

	cout << "Returned val: " << get(MySChar) << endl;

	return 0;
}

How would I do that the proper way? :S

 

Share this post


Link to post
Share on other sites
47 minutes ago, MarcusAseth said:

I was doing an experiment, code below:


template<typename T>
struct S
{
	explicit S(T v) :val{ v } {};
	T val;
};

int main()
{
	S<int> MyS('g');
	cout << MyS.val << endl;//Output is 103

	return 0;
}

Even though I am providing T with a type which is int, and I have an explicit constructor, why I have an implicit conversion from char to int? Shouldn't it see that T is int since I'm telling it so and thus give me error for constructing an S out of char?

 

 

In C++ words, this is called promotion. Promotions happen automatically.

See for example Integral promotion of this page.

Share this post


Link to post
Share on other sites

Well, I kind of found a solution to my last question (by throwing everything at random at it), which is auto& return type. But still out of curiosity, what would be the second best alternative to auto, using templates? :P

template <typename T>
auto& get(T& e)
{
	return e.val;
}

 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

You're probably looking for the decltype keyword, but this is all too abstract for me to even work out what you're trying to do at a glance.

Share this post


Link to post
Share on other sites
15 minutes ago, Kylotan said:

but this is all too abstract for me to even work out what you're trying to do at a glance.

nothing too fancy, I'm just trying to make the code below compile without changing it but just by modifying that get() function 

The code below the commented line that says "//THIS 5 LINES BELOW NEEDS TO COMPILE"

int main()
{
	S<int> MySInt(5);
	S<char> MySChar('B');
	S<double> MySDouble(2.2);
	S<string> MySString(string("wow!"));
	S<vector<int>> MySVec(vector<int>(4, 99));

	cout << "MySInt: " << MySInt.val << endl;
	cout << "MySChar: " << MySChar.val << endl;
	cout << "MySDouble: " << MySDouble.val << endl;
	cout << "MySString: " << MySString.val << endl;

	cout << "MySVec: ";
	for (auto& e : MySVec.val)
		cout << e << " ";
	cout << endl;

	//THIS 5 LINES BELOW NEEDS TO COMPILE
	cout << "Returned val from get(): " << get(MySInt) << endl;
	cout << "Returned val from get(): " << get(MySChar) << endl;
	cout << "Returned val from get(): " << get(MySDouble) << endl;
	cout << "Returned val from get(): " << get(MySString) << endl;
	cout << "Returned val from get(): " << get(MySVec)[0] << endl;

	return 0;
}

So this is the function with decltype (assuming I am using it correctly) but doesn't work as well :/

template <typename T, typename R>
R& get(T& e)
{
	decltype(e.val) R;
	return e.val;
}

auto& as return type works just fine and those 5 lines compile, I was just wondering if there where any other ways :P 

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

Moving to a new question, why is the code below not compiling if I uncomment one of the 4 commented-out lines ?

Function "set(Container, newValue, ID)"  takes a "MyContainer" class, a new value to set and an optional ID, just in case is a MyContainer<vector<int>>.

inside of it, takes the "val" of the MyContainer which returns wathever it is containing, in the example case is indeed a vector<int>&, but as soon as I try to use an operator<< or operator= on Vec, this thing doesn't compile...what am I not getting here? :S

template<typename T>
struct is_Container {
	static const bool value = false;
};

template<typename T, typename Alloc>
struct is_Container<vector<T,Alloc>> {
	static const bool value = true;
};

template <typename T, typename V>
void set(MyContainer<T>& e, V newVal, int ID = 0)
{
	T& Val = e.get();
	if (is_Container<T>::value)
	{
		cout << "is a vector" << endl;
		//cout << Val[ID] << endl;
		//Val[ID] = newVal;
	}
	else
	{
		cout << "is not a container" << endl;
		//cout << Val << endl;
		//Val = newVal;
	}
}

GcucCqV.png

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!