最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Construct a variadic std::tuple using a parameter pack of constructor arguments - Stack Overflow

programmeradmin1浏览0评论

I have the following class definitions. I would like to create an Alphabet of Letter classes where each Letter class is constructed using an argument from the parameter pack passed to the Alphabet constructor.

#include <tuple>

struct ArgA {};
struct ArgB {};
struct ArgC {};

struct A
{
    A(ArgA& param) {}
};
struct B
{
    B(ArgB& param) {}
};
struct C
{
    C(ArgC& param) {}
};

template <typename ...TLetters>
struct Alphabet
{
    template <typename ...TArgs>
    Alphabet(TArgs& ...params) : _alphabet(TLetters(params...)...) {}

    std::tuple<TLetters...> _alphabet;
};

int main()
{
    ArgA argA; ArgB argB; ArgC argC;

    Alphabet<A>         alphabet1(argA);              // Compiles
    Alphabet<A, B>      alphabet2(argA, argB);        // Doesn't compile because argA and argB are passed to A, B and C constructors
    Alphabet<A, B, C>   alphabet3(argA, argB, argC);  // Ditto! 
}

The example doesn't compile once I add alphabet2 and alphabet3 as argA, argB and argC are ALL passed to each object's constructor in the TLetters parameter pack (rather than the argument pertaining to it).

Is this possible? Possibly using a std::integer_sequence to recursively iterate over the TArgs parameter pack on the Alphabet constructor? My compiler is only C++11 compliant.

Thanks!

I have the following class definitions. I would like to create an Alphabet of Letter classes where each Letter class is constructed using an argument from the parameter pack passed to the Alphabet constructor.

#include <tuple>

struct ArgA {};
struct ArgB {};
struct ArgC {};

struct A
{
    A(ArgA& param) {}
};
struct B
{
    B(ArgB& param) {}
};
struct C
{
    C(ArgC& param) {}
};

template <typename ...TLetters>
struct Alphabet
{
    template <typename ...TArgs>
    Alphabet(TArgs& ...params) : _alphabet(TLetters(params...)...) {}

    std::tuple<TLetters...> _alphabet;
};

int main()
{
    ArgA argA; ArgB argB; ArgC argC;

    Alphabet<A>         alphabet1(argA);              // Compiles
    Alphabet<A, B>      alphabet2(argA, argB);        // Doesn't compile because argA and argB are passed to A, B and C constructors
    Alphabet<A, B, C>   alphabet3(argA, argB, argC);  // Ditto! 
}

The example doesn't compile once I add alphabet2 and alphabet3 as argA, argB and argC are ALL passed to each object's constructor in the TLetters parameter pack (rather than the argument pertaining to it).

Is this possible? Possibly using a std::integer_sequence to recursively iterate over the TArgs parameter pack on the Alphabet constructor? My compiler is only C++11 compliant.

Thanks!

Share Improve this question edited Jan 20 at 12:17 463035818_is_not_an_ai 122k11 gold badges99 silver badges208 bronze badges asked Jan 20 at 9:52 pic32cpppic32cpp 715 bronze badges 2
  • 2 Are you not expanding the pack twice? I would try Alphabet(TArgs& ...params) : _alphabet(TLetters(params)...) {} – BoP Commented Jan 20 at 10:00
  • 1 Side note: to make your snippet work, you should add the missing #include <tuple>, so one can directly copy/paste it and try it. – edrezen Commented Jan 20 at 10:03
Add a comment  | 

2 Answers 2

Reset to default 3

You should understand what this TLetters(params...)... expression does.

You have used ... twice, so for Alphabet<A, B> alphabet2(argA, argB); this will expand the expression TLetters(params...)... to:

A(argA, argB), B(argA, argB)

Which is clearly invalid, since A or B do not have matching constructors.

The alternative answer is the simplest fix, but another possible modification of your code is to just drop the extra ...:

    template <typename ...TArgs>
    Alphabet(TArgs& ...params) : _alphabet(TLetters(params)...) {}

So in case of Alphabet<A, B> alphabet2(argA, argB); the problematic expression will expand to the expected: A(argA), B(argB)

https://godbolt.org/z/feo33qhn9

template <typename ...TLetters>
struct Alphabet
{
    template <typename ...TArgs>
    Alphabet(TArgs& ...params) : _alphabet(params...) {}

    std::tuple<TLetters...> _alphabet;
};

It's unnecessary to put TLetters in the constructor

Demo

发布评论

评论列表(0)

  1. 暂无评论