Why can't I use abstract types in tuples I never instantiate?

https://ideone.com/Uy49wa
http://coliru.stacked-crooked.com/a/02fa7173c64236a4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <tuple>
#include <typeinfo>

struct Test
{
	virtual ~Test() = 0;
};
inline Test::~Test() = default;

template<typename T>
void f()
{
	std::cout << typeid(T).name() << std::endl;
}

int main()
{
	f<std::tuple<Test>>();
}
This code fails in both GCC and Clang, even though I am 100% positive it used to work under clang previously. The code never tries to create an instance of the tuple, so why should this code fail? I'm using tuples as type vectors and not being able to use abstract classes is a huge pain.

EDIT: It appears that GCC has had this issue for years:
https://ideone.com/7Qkm2E

EDIT: MSVC accepts the code without issue - I believe when I had it working in clang, clang was using MSVC's standard library.
Last edited on
See this:

http://en.cppreference.com/w/cpp/language/typeid

When applied to an expression of polymorphic type, evaluation of a typeid expression may involve runtime overhead (a virtual table lookup), otherwise typeid expression is resolved at compile time.
I'd say that this requires that the class needs a kind of internal instance.

Does it even make sense to have a name of an object that cannot be an object?
In the other example I linked to, typeid is never used and the code still fails with the same error. In my actual code typeid is never used. I just used typeid as an example.
coder777 wrote:
Does it even make sense to have a name of an object that cannot be an object?
Yes, in my case it does. I'm collecting all classes in a hierarchy into a tuple and removing duplicates. Some of the classes are purely abstract but they still need to be included.
I just found out it happens with void too: https://ideone.com/1PSGzH

I'm pretty sure it's supposed to be allowed, it must be a standard library implementation bug that's been around for quite a while :(
> I'm pretty sure it's supposed to be allowed, it must be a standard library implementation bug

This error is related to the core language; it has nothing to do with implementation details of the standard library.
And AFAIK, it is not a bug; it is an error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <typeinfo>

struct A { virtual void f() const = 0 ; };

template < typename T > struct B { T v ; };

int main()
{
    typeid(A) ; // fine: A can be instantiated as a sub-object
    sizeof(A) ; // fine: A can be instantiated as a sub-object

    typeid( B<A> ) ; // *** may be error: the implementation is not required to maintain type_info objects for 'impossible' types 
    sizeof( B<A> ) ; // *** definite error: sizeof 'impossible' type
}

http://coliru.stacked-crooked.com/a/97c9ddd0450c7e3d
http://rextester.com/TJZHC17968
Last edited on
My actual code generates the same error message without using typeid or sizeof.

This is my actual code (condensed): https://ideone.com/pIlQYv
> My actual code generates the same error message without using typeid or sizeof

But you are using std::tuple_cat<>

template <class... Tuples>
constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);

In the following paragraphs, let Ti be the ith type in Tuples, Ui be remove_reference_t<Ti>, and tpi be the ith parameter in the function parameter pack tpls, where all indexing is zero-based.

Requires: For all i, Ui shall be the type cvi tuple<Argsi ...>, where cvi is the (possibly empty) ith cv-qualifier-seq and Argsi is the parameter pack representing the element types in Ui . Let Aik be the kith type in Argsi . For all Aik the following requirements shall be satisfied:

If Ti is deduced as an lvalue reference type, then is_constructible<Aik , cvi Aik&>::value == true,
otherwise is_constructible<Aik , cvi Aik&&>::value == true.

(Emphasis added.)

http://coliru.stacked-crooked.com/a/64f307555deb26b9
Ah, I didn't know that restriction existed. I've worked around it by just writing my own tuple type that doesn't store any data. Thanks!
Topic archived. No new replies allowed.