How to use sfinae for selecting constructors? [duplicate]
You can add a defaulted type argument to the template: template <int otherN, typename = typename std::enable_if<otherN >= N>::type> explicit A(A<otherN> const &);
You can add a defaulted type argument to the template: template <int otherN, typename = typename std::enable_if<otherN >= N>::type> explicit A(A<otherN> const &);
Nicol’s solution works fine, but this is an alternative: template<typename T> struct Base { void print1() {cout << “Base::print1” << endl;}; void print2() {cout << “Base::print2” << endl;}; }; template<> void Base<int>::print2() {cout << “Base<int>::print2()” << endl;}; That way you can specialize only specific member functions and still use those that you haven’t specialized(in this … Read more
(IMHO) The most common reasons the standard disallows a specific feature are: The feature is covered by another mechanism in the language, rendering it superfluous. It contradicts existing language logic and implementation, making its implementation potentially code breaking. Legacy: the feature was left out in the first place and now we’ve built a lot without … Read more
You can use some ugly SFINAE with std::enable_if, but I’m not sure it is better than your initial solution (in fact, I’m pretty sure it’s worse!): #include <memory> #include <type_traits> // helper that was not included in C++11 template<bool B, typename T = void> using disable_if = std::enable_if<!B, T>; template<typename T> struct Foo { Foo() … Read more
To be able to take a pointer to A, and reinterpret it as a pointer to B, they must be pointer-interconvertible. Pointer-interconvertible is about objects, not types of objects. In C++, there are objects at places. If you have a Big at a particular spot with at least one member existing, there is also a … Read more
I’m two months late, but I’m having the exact same problem right now and I think I’ve found some sort of an answer. The short version is that it should work, but I’m not sure if I’d depend on it. Here’s what I found: The C++11 standard defines a new memory model, but it has … Read more
According to the standard, 8.4.1, a declarator for a function includes the trailing-return-type, and a class function definition contains “declarator virt-specifier-seqopt“. The second one, virt-specifier-seq, is one of final or override, so those come after the trailing return type. (I.e. Clang gets it right.)
It’s fine with or without the std::move. The name of a local variable* is treated as an rvalue in the return statement, causing the move constructor to be invoked in both cases. The authors presumably used std::move for stylistic reasons, to make it clear that the lock is being moved. It does interfere with NRVO, … Read more
A segfault is outside of C++’s exception system. If you dereference a null pointer, you don’t get any kind of exception thrown (well, atleast if you comply with the Require: clause; see below for details). For operator->, it’s typically implemented as simply return m_ptr; (or return get(); for unique_ptr). As you can see, the operator … Read more
The surprise This is a subtle Clang bug, deeply buried in the Standard. The problem is that in almost all cases, non-type template arguments can be converted to the type of the template parameter. E.g. the expression Int<0> has an int literal argument of value 0 that is being converted to the type unsigned long … Read more