代码之家  ›  专栏  ›  技术社区  ›  Anycorn

C++将隐含构造限制为特定值

  •  1
  • Anycorn  · 技术社区  · 15 年前

    假设:

    struct P {
        P(int v);
    };
    
    int v;
    P p = 0; // allow
    P q = v; // Fail at compile time
    

    怎样才能做到?有模板技巧吗?

    我正在尝试编写具有特殊指针属性的分配器。遗憾的是,Std实现使用了从int到null指针的隐式转换:

    { return __n != 0 ? _M_impl.allocate(__n) : 0; }
    

    我的指针实现: http://code.google.com/p/asadchev/source/browse/trunk/projects/boost/cuda/mapped_ptr.hpp

    我的分配器实现: http://code.google.com/p/asadchev/source/browse/trunk/projects/boost/cuda/allocator.hpp

    我想使用原始指针强制显式构造,以避免令人讨厌的问题。

    6 回复  |  直到 15 年前
        1
  •  6
  •   Johannes Schaub - litb    15 年前

    你能做到,但你不会喜欢的

    struct P {
    private:
        struct null_absorb;
    
    public:
        P(null_absorb *v);
    };
    
    int v;
    P p = 0; // allow
    P q = v; // Fail at compile time
    

    这将只允许空指针常量。换句话说,编译时间值为零。

        2
  •  3
  •   Oliver Charlesworth    15 年前

    我不知道你为什么要这么做,但有点像:

    struct P
    {
    protected:
        P(int v) {}
    
    public:
        template <int N>
        static P create() { return P(N); }
    
    };
    
    int main()
    {
        P p = P::create<0>();
    }
    
        3
  •  2
  •   Michael Kristofik    15 年前

    是否确实要允许隐式转换 int ?这可能会导致许多意外的编码错误。因为传递0以外的任何东西都是一个编码错误,所以您可以执行以下操作之一:

    #include <cassert>
    struct P
    {
        // Option #1, only allow 0 as an argument.
        explicit P(int v)
        {
            assert(v == 0);
            // other stuff goes here.
        }
    
        // Option #2, provide a no-argument constructor.
        P()
        {
            // behave like P(0)
        }
    };
    
        4
  •  1
  •   Reinderien    15 年前

    我认为没有任何直接的方法来区分文字和变量,就像你想要的那样。另一种选择是要求构造函数接受对整数的引用:这可以使用变量,但不能使用文本。

        5
  •  0
  •   user318904    15 年前

    C++的静态断言可能会起到作用: http://www.skynet.ie/~caolan/Fragments/C++StaticAssert.html

    但是我认为它来自更新的C++。

    另外,在编译时将其初始化为零怎么样?也许会保持不变。

        6
  •  0
  •   Albert    15 年前

    怎么办:

    struct P {
        P(int v) { assert(v == 0); }
    };
    

    如果您错误地使用它,一些编译器甚至可能会在编译时看到它。