Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
168 views
in Technique[技术] by (71.8m points)

c++ - Fallback variadic constructor - why does this work?

In answering this question about trying to construct a variadic forwarding reference constructor that should only be called if no other constructor is valid. That is, if there was a:

C(const char*, size_t) { }                     // 1
template <typename... T, ???> C(T&&... ) { }   // 2

We'd want C c1{"abc", 2}; to call (1), despite the required conversion, but C c2{1, 2, 3}; to call (2), as (1) cannot apply.

I proposed the following solution:

template <typename... T,
          typename = std::enable_if_t<!std::is_constructible<C, T&&...>::value>
           >
C(T&&... ) { }

And by proposed, I mean, I tried it and was surprised to discover that it actually works. It compiles and does exactly what I had hoped for on both gcc and clang. However, I am at a loss to explain why it works or even if it's actually supposed to work and gcc and clang are both just being particularly accommodating. Is it? Why?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The issue with your code is that we just instantiated is_constructible in a context where it gets the answer wrong. Any kind of caching in the template code is likely to result in bugs -- try printing is_constructible on the same parameters after you call the constructor! It is likely to get it wrong.

Live example of how it can go wrong. Notice it claims C cannot be constructed from an int&, despite having done so on the previous line.

struct C {
  C(const char*, size_t) {}
  template <class... Ts,
    typename = std::enable_if_t<!std::is_constructible<C, Ts&&...>::value>
  >
  C(Ts&&... ) { }
};

int main() {
  int a = 0;
  C x{a};
  std::cout << std::is_constructible<C, int&>{} << '
';
}

oops.

I suspect this might be an ODR violation -- the two definitions of is_constructible have different types at different spots? Or maybe not.

Solution to the original problem that does not have this issue also posted.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...