3

Related to this question, I want to specify my private section after my public interface.

template<class T, void (T::*f)()>
class B
{
public:
    void g(int y) noexcept(noexcept(x.*f()))
    {}
private:
    T& x;
};

But I get an error from Clang that x is an undeclared identifyer.

mm_test.cpp:14:34: error: use of undeclared identifier 'x'
    void g(int y) noexcept(noexcept(x.*f()))
                                    ^

It compiles just fine if the declaration of member x occurs before the declaration of g. Am I not supposed to be able to use a member variable in a noexcept operator earlier in the class definition than its declaration? If not, how could I achieve an equivalent noexcept specifier without moving the declaration of x ahead?

Community
  • 1
  • 1
John
  • 7,301
  • 2
  • 16
  • 23
  • 3
    `noexcept(std::declval().*f())` perhaps? – user657267 Dec 02 '14 at 04:42
  • 1
    `noexcept(noexcept(this->x.*f()))` should work too, although gcc doesn't accept it due to [this bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52869). – Praetorian Dec 02 '14 at 05:18
  • 1
    @user657267 `noexcept(std::declval().*f())`, more precisely. – Arne Mertz Dec 02 '14 at 08:00
  • @ArneMertz Why T& over T? I presume `declval` is just dressing over a null dereference, why would return by reference vs value matter in an unevaluated context? – John Dec 02 '14 at 16:11
  • 3
    @John There's no null dereference going on in [`declval`](http://en.cppreference.com/w/cpp/utility/declval), it doesn't even have a definition. In this case `declval` vs `declval` doesn't make a difference, but [it could if the function pointer template parameter had a ref qualifier](http://coliru.stacked-crooked.com/a/07caee3cdd30ca00). Since the intent seems to be to invoke the member function on an lvalue reference to the object, it's a good idea to match that in the `declval` expression as well. – Praetorian Dec 03 '14 at 03:34
  • @John declval is only a function that is *declared* to return exaclty what you provide as template parameter. The compiler does not execute any of the expressions inside the noexcept operator, it only evaluates what types are involved and what functions are called on those types. Read `noexcept(std::declval().*f())` as "if there *was* a `T&`, and you called `f()` on it, what would the `noexcept` specification of that call be?" – Arne Mertz Dec 04 '14 at 09:22

0 Answers0