2

I have the following code from Ben Deane talk.

#define CX_VALUE(...) [] { \
    struct { \
        constexpr auto operator()() const noexcept { return __VA_ARGS__; } \
        using cx_value_tag = void; \
    } val; \
    return val; \
}()

template <typename T>
concept cx_value = requires { typename T::cx_value_tag; };

auto func(cx_value auto x) { 
    constexpr auto val = x();
    std::cout << "Constexpr value: " << val.val() << '\n';
}

class S {
    public:
    constexpr S(const int val) :  val_(val){}
    int val() const {
        return val_;
    }
    private:
    int val_;
};

int main() {
    constexpr S non_structural_value{420};
    func(CX_VALUE(non_structural_value));
}

Issue is that clang rejects it, gcc accepts it.

Which compiler is right(or is it maybe underspecified in the standard)?

2

1 Answer 1

4

This has nothing to do with the properties of the class S.

The problem can be reduced to

struct S {};
int main() {
    constexpr S s{};
    []{
        struct {
            constexpr auto operator()() { return s; }
        } val;
    };
}

The problem is that s is being odr-used here in return s; because it doesn't have the lvalue-to-rvalue conversion applied to it (because it is of class type). And s is not odr-usable in this scope.

For the same reason you would need to capture s if you tried to write []{ return s; } instead. But in the case above capturing won't help either, s will still not be odr-usable in the scope of the local class.

Clang is correct.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.