atlascoder
atlascoder

Reputation: 3063

Declaring class member with deduced type

I have a code that uses type deduction like this:

template <typename... Ttypes>
Tuple<Ttypes...> makeTuple(Ttypes... args) {
   Tuple<Ttypes...> result;
   fillTuple<0>(result, args...);
   return result;
}

I want to encapsulate the result to a class which is not a class template. The only way, and this is reasonable, is to have it as a static const member like this:

struct A {
    static const auto t = makeTuple(1,2,3,'c');
};

and I get: error: in-class initializer for static data member of type 'const Tuple<int, int, int, char>' requires 'constexpr' specifier static const auto tuple = makeTuple(1,2,3,'c');.

If I use

struct A {
    static const auto constexpr t = makeTuple(1,2,3,'c');
};

I get error: constexpr variable 'tuple' must be initialized by a constant expression.

Moreover, using constexpr is not good for me, because I' like to use non-literal types in a tuple.

Compiler Clang with -std=c++14.

Is there a way to get what I want?

Upvotes: 0

Views: 764

Answers (2)

Kevin Bright
Kevin Bright

Reputation: 71

You should be able to accomplish this without declaring the member static. auto is useful for type deduction when it is also being initialized. If declaration is needed prior to initialization you can use decltype instead.

GeeksForGeeks has a good introduction to decltype. https://www.geeksforgeeks.org/type-inference-in-c-auto-and-decltype/

#include <iostream>
#include <tuple>
#include <memory>

using namespace std;

template<typename... Types>
tuple<Types...> makeTuple(Types... types)
{
    return tuple<Types...>();
}


//I'm using these two functions just to show 
//that non constexpr functions can be used to determine type
int generateInt()
{
    return 1;
}

char generateChar()
{
    return 'a';
}

struct A
{
    decltype(makeTuple(generateInt(), generateChar())) t;

    A() : t(makeTuple(1, 'a'))
    {

    }
};

int main()
{
    A a;

    return 0;
}

Upvotes: 1

Igor Tandetnik
Igor Tandetnik

Reputation: 52461

Something along these lines, perhaps:

struct A {
    using TupleType = decltype(makeTuple(1,2,3,'c'));
    static const TupleType  t;
};

// In a .cpp file
const A::TupleType A::t = makeTuple(1,2,3,'c');

Somewhat more elaborate, but avoids some repetition:

struct A {
    static auto MakeMyTuple() { return makeTuple(1,2,3,'c'); }
    using TupleType = decltype(MakeMyTuple());
    static const TupleType t;
};

// In a .cpp file
const A::TupleType A::t = A::MakeMyTuple();

This way, arguments to makeTuple are all in one place.

Upvotes: 2

Related Questions