Date: Sat, 20 Apr 2019 20:37:20 -0400
The reason that this doesn't work is because templated functions are not
instantiated (compiled into binary code) until they are used. The vtable
needs an actual address to point to, and is generated at the time that the
class is. As a templated function could have any type, it would be
impossible for a vtable to be generated that would be big enough to accept
any type. Well, maybe it could, but it would be impractical.
A possible way around this is to accept a proxy:
#include <assert.h>
class unexpected_type : std::exception {
char const* what() override { return "Unexpected type passed"; }
};
enum types
{
int_e, float_e
};
class Base
{
virtual int func(types) = 0;
};
class Child
{
int func_int() { return 1; }
int func_float() { return 0; };
int funct(types type) {
switch(type) {
case int_e: return func_int();
case float_e: return func_float();
default:
assert(false);
throw unexpected_type();
}
};
void main()
{
Base* p = new Child();
int i = p->func(int_e);
int j = p->func(float_e);
delete p;
}
Note that this is just one way. Another possible method would be to use a
class proxy that can have a virtual function to be able to tell the
programme what to do next. The virtual function would then accept the base
class. You might want to lookup type erasure c++
<https://www.google.com/search?q=type+erasure+c%2B%2B>.
HTH
A
<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Virus-free.
www.avg.com
<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
On Sat, Apr 20, 2019 at 3:17 PM Ritwik Das via Std-Discussion <
std-discussion_at_[hidden]> wrote:
> Hello,
> I am almost sure this has come up before so I am looking for reasons why
> this will not work or why this proposal has not been accepted by the
> standard committee.
>
> The following proposal does not change the way virtual functions work but
> only helps in writing them in a more easier and concise manner by allowing
> composability with template args.
>
> *Current approach:*
>
> class Base
> {
> virtual int func_int() = 0;
> virtual int func_float() = 0;
> };
>
> class Child
> {
> virtual int func_int() { return 1; }
> virtual int func_float() { return 0; };
> };
>
> void main()
> {
> Base* p = new Child();
> int i = p->func_int();
> int j = p->func_float();
> delete p;
> }
>
>
> *Proposal:*
>
> class Base
> {
> template<typename T>
> virtual int func() = 0;
> };
>
> class Child
> {
> template<typename T>
> virtual int func()
> {
> if (std::is_same_v<T, int>) return 0;
> return 1;
> }
> };
>
> void main()
> {
> Base* p = new Child();
> int i = p->func<int>(); // Internally the compiler can create
> named functions like func_int()
> int j = p->func<float>();
> delete p;
> }
> --
>
> Ritwik Das
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> http://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
instantiated (compiled into binary code) until they are used. The vtable
needs an actual address to point to, and is generated at the time that the
class is. As a templated function could have any type, it would be
impossible for a vtable to be generated that would be big enough to accept
any type. Well, maybe it could, but it would be impractical.
A possible way around this is to accept a proxy:
#include <assert.h>
class unexpected_type : std::exception {
char const* what() override { return "Unexpected type passed"; }
};
enum types
{
int_e, float_e
};
class Base
{
virtual int func(types) = 0;
};
class Child
{
int func_int() { return 1; }
int func_float() { return 0; };
int funct(types type) {
switch(type) {
case int_e: return func_int();
case float_e: return func_float();
default:
assert(false);
throw unexpected_type();
}
};
void main()
{
Base* p = new Child();
int i = p->func(int_e);
int j = p->func(float_e);
delete p;
}
Note that this is just one way. Another possible method would be to use a
class proxy that can have a virtual function to be able to tell the
programme what to do next. The virtual function would then accept the base
class. You might want to lookup type erasure c++
<https://www.google.com/search?q=type+erasure+c%2B%2B>.
HTH
A
<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Virus-free.
www.avg.com
<http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
On Sat, Apr 20, 2019 at 3:17 PM Ritwik Das via Std-Discussion <
std-discussion_at_[hidden]> wrote:
> Hello,
> I am almost sure this has come up before so I am looking for reasons why
> this will not work or why this proposal has not been accepted by the
> standard committee.
>
> The following proposal does not change the way virtual functions work but
> only helps in writing them in a more easier and concise manner by allowing
> composability with template args.
>
> *Current approach:*
>
> class Base
> {
> virtual int func_int() = 0;
> virtual int func_float() = 0;
> };
>
> class Child
> {
> virtual int func_int() { return 1; }
> virtual int func_float() { return 0; };
> };
>
> void main()
> {
> Base* p = new Child();
> int i = p->func_int();
> int j = p->func_float();
> delete p;
> }
>
>
> *Proposal:*
>
> class Base
> {
> template<typename T>
> virtual int func() = 0;
> };
>
> class Child
> {
> template<typename T>
> virtual int func()
> {
> if (std::is_same_v<T, int>) return 0;
> return 1;
> }
> };
>
> void main()
> {
> Base* p = new Child();
> int i = p->func<int>(); // Internally the compiler can create
> named functions like func_int()
> int j = p->func<float>();
> delete p;
> }
> --
>
> Ritwik Das
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> http://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
Received on 2019-04-20 19:39:09