如何使用 mpl 技术启用构造函数

发布于 2024-10-27 18:49:43 字数 955 浏览 2 评论 0原文

我对 boost::enable_if 以及如何用它进行构造函数切换有点困惑。

代码是这样的:

struct NullType{};
struct TestType{};
struct NonNull{};

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i, typename boost::enable_if<boost::is_same<U, NullType>, void* >::type dummy = 0)
    {
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j, typename boost::disable_if<boost::is_same<U, NullType>, void* >::type dummy = 0)
    {
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

int main(int /*argc*/, char**)
{
    TemplateStruct<TestType>(1);
    TemplateStruct<TestType,NonNull>(1,2);
    return 0;
}

我想要归档的内容如下。它希望第一个 Ctor 仅在给出 NullType 时才可用。在所有其他情况下,我想禁用第一个 Ctor 并启用第二个 Ctor。

目前,我收到编译错误,因为其中一个构造函数无效。但是我怎样才能使 Ctor 成为模板化的 Ctor 并重用类模板参数呢?

I am little stuck with boost::enable_if and how to make a constructor switch with it.

The code is this:

struct NullType{};
struct TestType{};
struct NonNull{};

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i, typename boost::enable_if<boost::is_same<U, NullType>, void* >::type dummy = 0)
    {
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j, typename boost::disable_if<boost::is_same<U, NullType>, void* >::type dummy = 0)
    {
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

int main(int /*argc*/, char**)
{
    TemplateStruct<TestType>(1);
    TemplateStruct<TestType,NonNull>(1,2);
    return 0;
}

What I want to archive is the following. It want that the first Ctor is only available when a NullType is given. In all other cases I want to disable the first Ctor and enable the second one.

At the moment I get a compile error because one of the constructors is invalid. But how can I make the Ctor a templated one and reuse the class template parameter?

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

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

发布评论

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

评论(3

水染的天色ゝ 2024-11-03 18:49:43

这是根据需要解决问题的一种方法:

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i)
    {
        boost::enable_if< boost::is_same<U,NullType>, void*>::type var = nullptr;
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j)
    {
        boost::disable_if< boost::is_same<U,NullType>, void*>::type var = nullptr;
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

int main()
{
    TemplateStruct<TestType>(1);
    TemplateStruct<TestType,NonNull>(1,2);
    //will not compile TemplateStruct<TestType>(1,2);
    //will not compile TemplateStruct<TestType,NonNull>(1);
}

EDIT1:或者假设您选择的编译器和您使用的 STL 实现支持 static_assert 和类型特征(即 VS 2010 ),如果尝试使用禁用的功能,您可以获得更好的错误消息ctor:

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i)
    {
        static_assert( std::is_same<U,NullType>::value, "Cannot use one parameter ctor if U is NullType!" );
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j)
    {
        static_assert( !std::is_same<U,NullType>::value, "Cannot use two parameter ctor if U is not NullType!" );
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

EDIT2: 或者如果你的 STL 中没有 is_same 但你有 static_assert:

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i)
    {
        static_assert( boost::is_same<U,NullType>::value, "Cannot use one parameter ctor if U is NullType!" );
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j)
    {
        static_assert( !boost::is_same<U,NullType>::value, "Cannot use two parameter ctor if U is not NullType!" );
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

This is one way to solve your problem as you want:

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i)
    {
        boost::enable_if< boost::is_same<U,NullType>, void*>::type var = nullptr;
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j)
    {
        boost::disable_if< boost::is_same<U,NullType>, void*>::type var = nullptr;
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

int main()
{
    TemplateStruct<TestType>(1);
    TemplateStruct<TestType,NonNull>(1,2);
    //will not compile TemplateStruct<TestType>(1,2);
    //will not compile TemplateStruct<TestType,NonNull>(1);
}

EDIT1: Or assuming your compiler of choice and the STL implementation you use supports static_assert and type traits (i.e. VS 2010 does) you can get better error messages if one tries to use the disabled ctor:

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i)
    {
        static_assert( std::is_same<U,NullType>::value, "Cannot use one parameter ctor if U is NullType!" );
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j)
    {
        static_assert( !std::is_same<U,NullType>::value, "Cannot use two parameter ctor if U is not NullType!" );
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

EDIT2: Or if no is_same in your STL but you have static_assert:

template<typename T, typename U = NullType>
struct TemplateStruct
{
    TemplateStruct(int i)
    {
        static_assert( boost::is_same<U,NullType>::value, "Cannot use one parameter ctor if U is NullType!" );
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j)
    {
        static_assert( !boost::is_same<U,NullType>::value, "Cannot use two parameter ctor if U is not NullType!" );
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};
遗弃M 2024-11-03 18:49:43

我不知道你的确切问题的解决方案。

也许这段代码会有所帮助(请注意,您不需要enable_if机制)。至少它可能是更好的解决方案的起点:

#include <iostream>

struct NullType{};
struct TestType{};
struct NonNull{};

template<typename T, typename U>
struct TemplateStruct
{  
    TemplateStruct(int i, int j)
    {
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

template<typename T>
struct TemplateStruct<T, NullType>
{
    TemplateStruct(int i)
    {
        std::cout << "One Param == " << i << std::endl;
    }
};

int main(int /*argc*/, char**)
{
    TemplateStruct<TestType,NullType>(1);
    TemplateStruct<TestType,NonNull>(1,2);
    return 0;
}

如果专门化 TemplateStruct<> ,那将不起作用。是不可取的/不可能的,或者您不想指定 NullType。

关于您对代码膨胀的担忧,我怀疑它是否相关:只有实例化的内容才能获取目标代码。

I don't know solution to your exact problem.

Maybe this code would help (notice that you don't need enable_if machinery for that). At least it could be starting point for nicer solution:

#include <iostream>

struct NullType{};
struct TestType{};
struct NonNull{};

template<typename T, typename U>
struct TemplateStruct
{  
    TemplateStruct(int i, int j)
    {
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }
};

template<typename T>
struct TemplateStruct<T, NullType>
{
    TemplateStruct(int i)
    {
        std::cout << "One Param == " << i << std::endl;
    }
};

int main(int /*argc*/, char**)
{
    TemplateStruct<TestType,NullType>(1);
    TemplateStruct<TestType,NonNull>(1,2);
    return 0;
}

That won't work if specializing TemplateStruct<> is undesirable/impossible or you don't want to specify NullType.

Regarding your concern about code bloat, I doubt it is relevant: only what was instantiated gets to object code.

此岸叶落 2024-11-03 18:49:43

解决这个问题的一种方法是在实际类周围有一个小包装器,然后专门化该包装器。如果您只想启用/禁用几个功能,那么这很有效。

struct NullType{};
struct TestType{};
struct NonNull{};

template<typename T, typename U>
struct TemplateStruct
{
    TemplateStruct(int i){
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j){
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }

    void FunctionToDisableFor1Param(){
    }

    void FunctionToAlwaysEnable(){
    }
};

template<class T, class U = NullType>
struct TSWrapper : public TemplateStruct<T,U>{
    typedef TemplateStruct<T,U> BaseType;

    TSWrapper(int i, int j)
        : BaseType(i,j)
    {}
};

template<class T>
struct TSWrapper<T,NullType> : public TemplateStruct<T,NullType>{
    typedef TemplateStruct<T,NullType> BaseType;

    TSWrapper(int i)
        : BaseType(i)
    {}

private:
    using BaseType::FunctionToDisableFor1Param;
};

int main()
{
    TSWrapper<TestType> x(1);
    TSWrapper<TestType,NonNull> y(1,2);
    x.FunctionToAlwaysEnable();
    y.FunctionToDisableFor1Param();
    // uncomment for compile time error
    //x.FunctionToDisableFor1Param();
    return 0;
}

One way to solve this, is to have a small wrapper around the actual class and just specialize that wrapper. This works well if you only wan't to enable/disable a couple of functions.

struct NullType{};
struct TestType{};
struct NonNull{};

template<typename T, typename U>
struct TemplateStruct
{
    TemplateStruct(int i){
        std::cout << "One Param == " << i << std::endl;
    }

    TemplateStruct(int i, int j){
        std::cout << "Two Param == " << i << "," << j << std::endl;
    }

    void FunctionToDisableFor1Param(){
    }

    void FunctionToAlwaysEnable(){
    }
};

template<class T, class U = NullType>
struct TSWrapper : public TemplateStruct<T,U>{
    typedef TemplateStruct<T,U> BaseType;

    TSWrapper(int i, int j)
        : BaseType(i,j)
    {}
};

template<class T>
struct TSWrapper<T,NullType> : public TemplateStruct<T,NullType>{
    typedef TemplateStruct<T,NullType> BaseType;

    TSWrapper(int i)
        : BaseType(i)
    {}

private:
    using BaseType::FunctionToDisableFor1Param;
};

int main()
{
    TSWrapper<TestType> x(1);
    TSWrapper<TestType,NonNull> y(1,2);
    x.FunctionToAlwaysEnable();
    y.FunctionToDisableFor1Param();
    // uncomment for compile time error
    //x.FunctionToDisableFor1Param();
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文