指示汇编时间叫什么构造函数

Indicate compile time what constructor was called

本文关键字:什么 构造函数 时间 汇编 指示      更新时间:2023-10-16

我有以下类

template<typename T>
class A
{
public:
   A(T* d)  : ptr(d)
   {}
   A(const T* d) : ptr(const_cast<T*>(d))
   {}
   T* Ptr()
   {
       static_assert(???, "Not allowed when using A(const T* d)");
       return ptr;
   }
   const T* Ptr() const
   {
       return ptr;
   }
private:
   T* ptr;
}

在编译ptr()时,我知道如何实现这一目标,我知道使用哪个构造函数来创建此对象?我想静态地断言,当汇编ptr()时,使用了consstructor a(t* d):

unsigned char* ptr = new unsigned char[10];
const unsigned char* cptr = new unsigned char[10];
A a(ptr);
A ca(cptr);
a.Ptr(); // Compiles
ca.Ptr(); // Gives compile error

我想检测到编译时间,如果程序员使用const ptr创建A类的对象时,请调用PTR()。不允许使用const ptr创建时调用foo

我想像这个

一样使用它
void Foo(A<int>& r)
{
 ....
 int* ptr = a.Ptr();
 ....
}
void Bar(const A<int>& r)
{
  ...
}
...
A a(ptr);
A ca(cptr);
Bar(a);
Bar(ac);
Foo(a);
Foo(ac);// Gives compile error

最简单的C 17(我可以告诉您无论如何都使用它来推断模板参数类型)方法是使用用户定义的扣除指南和其他标记非类型的非类型模板参数:

enum Tag {                       // 
    NonConstTag,                 //   Additional tag enum
    ConstTag                     //
};                               //
template<typename T, Tag TT>
//                   ^^^^^^
// Additional non-type template parameter to provide
// different type of A in case of calling const parameter 
// constructor
class A
{
public:
   A(T* d)  : ptr(d)
   {}
   A(const T* d) : ptr(const_cast<T*>(d))
   {}
   T* Ptr()
   {
       static_assert(TT == NonConstTag, "Not allowed when using A(const T* d)");
       return ptr;
   }
   const T* Ptr() const
   {
       return ptr;
   }
private:
   T* ptr;
};
template<typename T>             //
A(T* d) -> A<T, NonConstTag>;    //
                                 //    Deduction guides
template<typename T>             //
A(const T* d) -> A<T, ConstTag>; //
int main() {
    unsigned char* ptr = new unsigned char[10];
    const unsigned char* cptr = new unsigned char[10];
    A a(ptr);
    A ca(cptr);
    a.Ptr(); // Compiles
    //ca.Ptr(); // Gives compile error
}

[live demo]


编辑:

有点改进以满足const正确性:

enum Tag {
    NonConstTag,
    ConstTag
};
template<typename T, Tag TT>
class A
{
public:
   A(T* d)  : ptr(d), cptr(d)
   {}
   A(const T* d) : ptr(nullptr), cptr(d)
   {}
   T* Ptr()
   {
       static_assert(TT == NonConstTag, "Not allowed when using A(const T* d)");
       return ptr;
   }
   const T* Ptr() const
   {
       return cptr;
   }
private:
   T* ptr;
   const T* cptr;
};
template<typename T>
A(T* d) -> A<T, NonConstTag>;
template<typename T>
A(const T* d) -> A<T, ConstTag>;
int main() {
    unsigned char* ptr = new unsigned char[10];
    const unsigned char* cptr = new unsigned char[10];
    A a(ptr);
    A ca(cptr);
    a.Ptr(); // Compiles
    //ca.Ptr(); // Gives compile error
}

[live demo]

如果您有IDE,则可以使您跳到与呼叫相对应的声明。(YouCompleteme在VIM中使用:YcmCompleter GoTo来做到这一点;如果我没记错的话,Visual Studio具有F12或Alt-F12)。

)。

除此之外,如果要检测到运行时,请设置标志:

template <typename T> class A {
  public:
    A(T *) {}
    A(const T *) : used_const_arg_ctor(true) {}
  private:
    bool used_const_arg_ctor = false;
    void Foo() {
        if (used_const_arg_ctor) {
        }
    }
};

实际静态断言,使其成为constexpr类型:

#include <boost/asio.hpp>
template <typename T> class A {
  public:
    constexpr A(T *) {}
    constexpr A(const T *) : used_const_arg_ctor(true) {}
    constexpr bool Foo() const {
        return used_const_arg_ctor;
    }
  private:
    bool used_const_arg_ctor = false;
};
int main() {
    int const i = 42;
    constexpr A<int> a(&i);
    static_assert(a.Foo(), "is constructed from const pointer");
}

这有限。我建议让T反映constness:

template <typename T> class A {
  public:
    A(T*d) : _v(d) {}
    constexpr bool IsConst() const { return std::is_const<T>::value; }
  private:
    T* _v;
};