Towards an is_instantiable type trait?

78 views
Skip to first unread message

Vincent Reverdy

unread,
Apr 9, 2018, 1:06:48 AM4/9/18
to ISO C++ Standard - Future Proposals
Hello all,

I've been wondering lately whether an is_instantiable type trait would be any useful, and if so why, and how it would be defined. I am pretty neutral on the subject, so this thread is more an exploration of the idea than any concrete proposal. As always constructive feedback is welcome, as well as discussions on ideas.

So first, let's define what we are talking about:
template <class T>
struct is_instantiable
{
   
static constexpr bool value = /* something */;
}

template <class T>
inline constexpr bool is_instantiable_v = is_instantiable<T>::value;

Currently the standard has these related traits:
template <class T> struct is_abstract;
template <class T> struct is_[*]_constructible;
template <class T> struct is_[*]_destructible;

I've searched but I am not sure that the standards actually defines what it means that a type can be instantiated even if we (at least "think we") know what it means. We could think that is_[*]_constructible gives us everything we need, but there are types that have deleted constructors that are nevertheless instantiable:

struct instantiable
{
    instantiable
() = delete;
    instantiable
(const instantiable&) = delete;
    instantiable
(instantiable&&) = delete;
    instantiable
& operator=(const instantiable&) = delete;
    instantiable
& operator=(instantiable&&) = delete;
   
int x = 0;
};
//instantiable x0; // not working
instantiable x1
{}; // working

So here are my questions to this group:
  • How does the standard defines what it means that a type can be instantiated? And if it's not clearly defined, is there anything we could define clearly? Or, on the contrary, instantiability is a very blurry notion because of reasons A, B, C (in that case please provide examples why it is a blurry notion)?
  • If one can define the notion of instantiability, do the current existing type traits already provide all we need to very easily test if a type is instantiable? (I don't think that's the case but I may have missed something)
  • If one can define the notion of instantiability and it is not directly covered by existing type traits, how could we implement is_instantiable (ie what should go in the /* something */ of the first code box) (if it's not doable without compiler magic, pseudo-code is welcome)
  • So far, none of the three previous questions were discussing the usefulness of such a trait, because definability + implementatibility versus usefulness are completely orthogonal notions. So for the last question let's discuss usefulness: would you have use cases in mind for such a trait?
Thank you very much for your feedback!
Best,

Vincent

Tony V E

unread,
Apr 9, 2018, 1:14:33 AM4/9/18
to ISO C++ Standard - Future Proposals
I don't see much use. 

If someone says, 'yes, it is instantiable', but then doesn't tell you how, what do you do to instantiate, just guess?


Sent from my BlackBerry portable Babbage Device
From: Vincent Reverdy
Sent: Monday, April 9, 2018 1:06 AM
To: ISO C++ Standard - Future Proposals
Subject: [std-proposals] Towards an is_instantiable type trait?

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/edee7e15-1c9c-4c4f-a359-9a4ab1ca1ed9%40isocpp.org.

Vincent Reverdy

unread,
Apr 9, 2018, 2:05:04 AM4/9/18
to ISO C++ Standard - Future Proposals
Maybe because you don't want to instantiate, but use it as a condition to decide of a behaviour in a template metaprogramming context.

template <template <class> class Template, class Type>
struct foo
: std::conditional_t<is_inheritable_v<Template<Type>> && is_instantiable_v<Template<Type>>, Template<Type>, std::monostate>
{
   
// something
};



Nicolas Lesser

unread,
Apr 9, 2018, 8:37:53 AM4/9/18
to std-pr...@isocpp.org
Please use another name, instantiation refers to only templates. In fact, every use of "instantiate" in your emails is just wrong.


On Mon, Apr 9, 2018, 7:06 AM Vincent Reverdy <vinc...@gmail.com> wrote:
Hello all,

I've been wondering lately whether an is_instantiable type trait would be any useful, and if so why, and how it would be defined. I am pretty neutral on the subject, so this thread is more an exploration of the idea than any concrete proposal. As always constructive feedback is welcome, as well as discussions on ideas.

So first, let's define what we are talking about:
template <class T>
struct is_instantiable
{
   
static constexpr bool value = /* something */;
}

template <class T>
inline constexpr bool is_instantiable_v = is_instantiable<T>::value;

Currently the standard has these related traits:
template <class T> struct is_abstract;
template <class T> struct is_[*]_constructible;
template <class T> struct is_[*]_destructible;

I've searched but I am not sure that the standards actually defines what it means that a type can be instantiated even if we (at least "think we") know what it means.

The reason for this is that "instantiate" is the wrong term. 

We could think that is_[*]_constructible gives us everything we need, but there are types that have deleted constructors that are nevertheless instantiable:

Yes, this is an unfortunate fact that aggregate initialization sometimes can ignore certain deleted constructors.

struct instantiable
{
    instantiable
() = delete;
    instantiable
(const instantiable&) = delete;
    instantiable
(instantiable&&) = delete;
    instantiable
& operator=(const instantiable&) = delete;
    instantiable
& operator=(instantiable&&) = delete;
   
int x = 0;
};
//instantiable x0; // not working
instantiable x1
{}; // working

So here are my questions to this group:
  • How does the standard defines what it means that a type can be instantiated?
It doesn't really. If type can be used outside of a template, then another function which does the same thing can also be instantiated using the same type.
  • And if it's not clearly defined, is there anything we could define clearly?
Don't need to IMO.
  • Or, on the contrary, instantiability is a very blurry notion because of reasons A, B, C (in that case please provide examples why it is a blurry notion)?
I don't think it's blurry, but it's not really a "notion" or property of a type in itself.
  • If one can define the notion of instantiability, do the current existing type traits already provide all we need to very easily test if a type is instantiable?
No, there is no test whenever something is initializable with aggregate initialization, which is what you are doing.

I'm getting really confused about your use of instantiate right now :). The existing type traits like std::is_*_constructible don't have one for aggregates, which is what you want.

Indeed, this is the only form of initialization that is not covered by existing type traits, which is basically what you're after. 

Note that EWG expressed interest not to have this weird behavior (where aggregate initialization bypasses the deleted constructor and other such counter intuitive behavior) so you'll have to find another use case for such a trait possibly in the future.
  • (I don't think that's the case but I may have missed something)
  • If one can define the notion of instantiability and it is not directly covered by existing type traits, how could we implement is_instantiable (ie what should go in the /* something */ of the first code box) (if it's not doable without compiler magic, pseudo-code is welcome)
Just like std::is_constructible but with braces instead of parens.
  • So far, none of the three previous questions were discussing the usefulness of such a trait, because definability + implementatibility versus usefulness are completely orthogonal notions. So for the last question let's discuss usefulness: would you have use cases in mind for such a trait?
A bit. I can imagine that functions like std::make_unique should differentiate between aggregates and "normal" classes. We have a type trait for the later, but not the former. Your proposed aggregate initialization trait would solve this by allowing more specialization.

Thank you very much for your feedback!
Best,

Vincent

--

Todd Fleming

unread,
Apr 15, 2018, 10:26:43 AM4/15/18
to ISO C++ Standard - Future Proposals
On Monday, April 9, 2018 at 8:37:53 AM UTC-4, Nicolas Lesser wrote:
Please use another name, instantiation refers to only templates. In fact, every use of "instantiate" in your emails is just wrong.

Unfortunately this term is commonly used this way in the wild, especially with languages which don't have templates. It'd be nice if C++ had a standardized single-word replacement for "begin the lifetime of". "construct" doesn't quite fit.

Todd

Nicolas Lesser

unread,
Apr 15, 2018, 11:04:46 AM4/15/18
to std-pr...@isocpp.org
Oh wow. I find "define" sufficient for everyday needs. Of course placement new is problematic if I use "define", but I don't talk about placement new often, so it's fine :) 

Reply all
Reply to author
Forward
0 new messages