5

I need to define a static member (not constexpr) with a complex (many template parameters) type. Therefore it would be desired to have something like this:

struct X {
    static auto x = makeObjectWithComplexType();
};

But it is not C++. So I tried to workaround it, and thought the snippet below would work, but it does not:

#include <string>

struct X {
    static auto abc() {
        return std::string();
    }

    static decltype(abc()) x;
};

decltype(abc()) X::x;

int main() {}

It fails with error: error: use of ‘static auto X::abc()’ before deduction of ‘auto`*

Is there any way to make the snippet above to work. Or is there any other way to define a static member with a deduced type?

nicolai
  • 1,140
  • 9
  • 17
  • 4
    @zneak: this is not a duplicate of that, in this question, there is no reference to the enclosing class. – geza Jul 24 '18 at 08:08
  • Is it not? Seems to me that the questions can be rephrased into one another and the answer applies. I had originally posted the same answer (put the function outside of the class scope) and then remembered that I know it because I asked that question. – zneak Jul 24 '18 at 08:09
  • @zneak: In that question, the problem is that the OP tries to use `Foo` in the definion of `Foo`. In this question, there's no such thing. – geza Jul 24 '18 at 08:10
  • @geza, the only difference is that ‘abc’ is not qualified. You could rewrite this as ‘X::abc’. – zneak Jul 24 '18 at 08:12
  • @zneak: that's only a workaround try by the OP. Look at the original problem. – geza Jul 24 '18 at 08:13
  • Does that actually change the intent of the question? I think that the one I linked explains why the first example can’t work, why the second one also doesn’t, and what can be done about it. OP asks how to make it work, and the question I linked provides just that. Would you have a better answer if I voted to reopen? – zneak Jul 24 '18 at 08:16
  • @zneak: Of course it changes the intent of the question. The original problem can be easily solved. – geza Jul 24 '18 at 08:17
  • @Tyker: That question cannot be solved, the answer tells that there is no solution. This question can be solved. – geza Jul 24 '18 at 08:24
  • 1
    As this question got closed improperly, I'll write the answer here: you can use `static std::decay_t x;`. And maybe you can remove the `decay_t`, if `makeObjectWithComplexType()` returns a type which doesn't need decaying. – geza Jul 24 '18 at 09:28
  • @geza, I just stumbled back here, and I'd like to point out that this works because `makeObjectWithComplexType()`, contrary to `abc()`, is outside the class scope. However, the error at hand relates to the fact that `abc()` is in the class scope. That is exactly what https://stackoverflow.com/questions/41842987/why-cant-the-type-of-my-class-static-auto-function-be-deduced-within-the-class addressed. From the code snippet, it appears clear to me that OP knows about decltype, and that to unblock them, they need to know that they can't use it for a static member while the class is incomplete. – zneak Sep 12 '18 at 21:17
  • @zneak: maybe, let's see, I've put an answer. – geza Sep 12 '18 at 22:42
  • @zneak is right in his previous comment. – nicolai Sep 18 '18 at 07:42

1 Answers1

3

If you have C++17, then you can do this:

struct X {
    static inline auto x = makeObjectWithComplexType();
};

If you don't, you unfortunately have to repeat makeObjectWithComplexType():

struct X {
    static decltype(makeObjectWithComplexType()) x; // declaration
};

auto X::x = makeObjectWithComplexType(); // definition

Note, that clang successfully compiles this version, but gcc and msvc don't. I'm not sure which compiler is right, so I've asked it in a question.


If you're interested, why your workaround doesn't work, check out this question: Why can't the type of my class-static auto function be deduced within the class scope?

geza
  • 28,403
  • 6
  • 61
  • 135
  • You may want to address why OP gets `error: use of ‘static auto X::abc()’ before deduction of ‘auto'*` when using a class member. – zneak Sep 12 '18 at 22:44
  • @zneak: I've added a reference to the question, which you referred. – geza Sep 12 '18 at 22:48