Public Group

## 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?

Edited by MarcusAseth

##### Share on other sites

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 on other sites

Thanks @Kylotan, I had grossly misunderstood the meaning of that keyword

##### 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 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?

##### 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.

##### 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?

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

Edited by MarcusAseth

##### 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 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

Edited by MarcusAseth

##### 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?

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;
}
}

Edited by MarcusAseth

1. 1
2. 2
JoeJ
17
3. 3
4. 4
frob
11
5. 5

• 13
• 16
• 13
• 20
• 13
• ### Forum Statistics

• Total Topics
632186
• Total Posts
3004637

×