在运行时选择 ctor 参数

发布于 2024-12-02 10:51:15 字数 430 浏览 2 评论 0原文

是否可以解决以下使用 mpl 在运行时选择参数的场景?

struct A {
    A(int number) { /* use number */ } };
struct B { };

template <typename T, int n>
struct A_or_B_Holder {
    A_or_B_Holder() : _t( /* void or 'n', depends on T */ ) { }
private:
    T _t;
};

A_or_B_Holder<B, void> b;
A_or_B_Holder<A, 3> a;

理想情况下,

A_or_B_Holder<B> b;
A_or_B_Holder<A, 3> a;

Is it possible to address the following scenario of choosing the argument at runtime with mpl?

struct A {
    A(int number) { /* use number */ } };
struct B { };

template <typename T, int n>
struct A_or_B_Holder {
    A_or_B_Holder() : _t( /* void or 'n', depends on T */ ) { }
private:
    T _t;
};

A_or_B_Holder<B, void> b;
A_or_B_Holder<A, 3> a;

Ideally,

A_or_B_Holder<B> b;
A_or_B_Holder<A, 3> a;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只等公子 2024-12-09 10:51:15

您的第一个问题是 void 是一种类型,而不是整数。您可以使模板接受两种类型,第二种是 boost::mpl::int_void

然后,您可以专门化整个结构,也可以将数据成员放入基类中并对其进行专门化。

#include <boost/mpl/int.hpp>

struct A {
    A(int number) { /* use number */ } };
struct B { };

template <class T, class Value>
struct A_or_B_Holder_Base{
    A_or_B_Holder_Base(): _t(Value::value) {}
protected:
    T _t;
};

template <class T>    
struct A_or_B_Holder_Base<T, void> {
    A_or_B_Holder_Base(): _t() {}
protected:
    T _t;
};

template <typename T, typename Value>
struct A_or_B_Holder : public A_or_B_Holder_Base<T, Value> {

};

using boost::mpl::int_;
A_or_B_Holder<A, int_<3> > x;
A_or_B_Holder<B, void> y;
A_or_B_Holder<A, void > w;  //error, no default constructor
A_or_B_Holder<B, int_<3> > z;  //error, no int constructor

更自然的可能是不要求参数是编译时常量(因为无论如何您都将编译时常量转换为运行时变量)。只需重载构造函数即可。

struct A {
    A(int number) { /* use number */ } };
struct B { };


template <typename T>
struct A_or_B_Holder {
    A_or_B_Holder() : _t( ) { }
    A_or_B_Holder(int number): _t(number) {}
private:
    T _t;
};

A_or_B_Holder<B> b;
A_or_B_Holder<A> a(3);

Your first problem is that void is a type, not an integer. You could make the template accept two types, the second being either boost::mpl::int_ or void.

Then you could either specialize the entire struct, or you could put the data member in a base class and specialize that.

#include <boost/mpl/int.hpp>

struct A {
    A(int number) { /* use number */ } };
struct B { };

template <class T, class Value>
struct A_or_B_Holder_Base{
    A_or_B_Holder_Base(): _t(Value::value) {}
protected:
    T _t;
};

template <class T>    
struct A_or_B_Holder_Base<T, void> {
    A_or_B_Holder_Base(): _t() {}
protected:
    T _t;
};

template <typename T, typename Value>
struct A_or_B_Holder : public A_or_B_Holder_Base<T, Value> {

};

using boost::mpl::int_;
A_or_B_Holder<A, int_<3> > x;
A_or_B_Holder<B, void> y;
A_or_B_Holder<A, void > w;  //error, no default constructor
A_or_B_Holder<B, int_<3> > z;  //error, no int constructor

More natural might be not to require the parameter to be a compile-time constant (as you are turning the compile-time constant into a run-time variable anyway). Just overload the constructor.

struct A {
    A(int number) { /* use number */ } };
struct B { };


template <typename T>
struct A_or_B_Holder {
    A_or_B_Holder() : _t( ) { }
    A_or_B_Holder(int number): _t(number) {}
private:
    T _t;
};

A_or_B_Holder<B> b;
A_or_B_Holder<A> a(3);
屌丝范 2024-12-09 10:51:15

您可以使用 Boost.Variant< /a>

#include <boost/variant.hpp>

struct A
{
};

struct B
{
    B(int)
    {
    }
};

int main()
{
    boost::variant<A, B> val;

    if (/*some condition*/)
    {
        val = A();
    }
    else
    {
        val = B(5);
    }
}

如果您对它的实现方式更感兴趣,而不是您可以使用什么,我建议您查看 Boost.AnyBoost.Variant

You could use a Boost.Variant

#include <boost/variant.hpp>

struct A
{
};

struct B
{
    B(int)
    {
    }
};

int main()
{
    boost::variant<A, B> val;

    if (/*some condition*/)
    {
        val = A();
    }
    else
    {
        val = B(5);
    }
}

If you are more interested in how this is implemented, rather than what you can use, I suggest you check out the implementations of Boost.Any and Boost.Variant.

你是暖光i 2024-12-09 10:51:15

我认为在运行时传递不同的参数是不可能的。您必须拥有所有 T 类型都具有的标准构造函数。您可以从 std::vector构造所有 T 类型,并使用它来传递可变数量的变量类型参数,但这是超级危险的。

但是,您的示例似乎实际上是在编译时而不是运行时决定的,这是可以解决的。

const int NO_INT_PARAM=INT_MIN;
template <typename T, int n>
struct A_or_B_Base {
    A_or_B_Holder() : _t(n) { }
private:
    T _t;
};
template <typename T>
struct A_or_B_Base<T, NO_INT_PARAM> {
    A_or_B_Holder() : _t() { }
private:
    T _t;
};
template <typename T, int n=NO_INT_PARAM>
struct A_or_B_Holder : A_or_B_Base<T, n>{
    A_or_B_Holder() : A_or_B_Base() { }
    /* other functions*/
};

A_or_B_Holder<A, 3> a; //uses A(3) constructor
A_or_B_Holder<B> b;  //uses B() constructor
A_or_B_Holder<A> c; //compiler error! A() doesn't exist!
A_or_B_Holder<B, 5> d;  //compiler error! B(5) doesn't exist!
A_or_B_Holder<B, NO_INT_PARAM> e;  //same as b, uses B() constructor

I think that passing different arguments at run time is impossible. You'll have to have a standard constructor that all T types will have. You can make all T types construct from std::vector<void*> and use that to pass a variable number of variable type arguments, but that's super dangerous.

However, your sample seems to actually be deciding at compile-time, not run-time, which is solvable.

const int NO_INT_PARAM=INT_MIN;
template <typename T, int n>
struct A_or_B_Base {
    A_or_B_Holder() : _t(n) { }
private:
    T _t;
};
template <typename T>
struct A_or_B_Base<T, NO_INT_PARAM> {
    A_or_B_Holder() : _t() { }
private:
    T _t;
};
template <typename T, int n=NO_INT_PARAM>
struct A_or_B_Holder : A_or_B_Base<T, n>{
    A_or_B_Holder() : A_or_B_Base() { }
    /* other functions*/
};

A_or_B_Holder<A, 3> a; //uses A(3) constructor
A_or_B_Holder<B> b;  //uses B() constructor
A_or_B_Holder<A> c; //compiler error! A() doesn't exist!
A_or_B_Holder<B, 5> d;  //compiler error! B(5) doesn't exist!
A_or_B_Holder<B, NO_INT_PARAM> e;  //same as b, uses B() constructor
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文