如果对象是堆栈创建的(包括继承类型),是否可能发出编译错误?

Is it possible to issue compile error if object is stack created (including inherited types)?

基本上我希望所有子类型都通过工厂方法创建(我有一个很高的域层次结构,大约有 200 多个 classes)。

对于 new,这不是问题,因为这可以在 A 中被覆盖(使 new 私有)。

class A{
protected:
  A();
public:
  template<class T, typename... ARGUMENTS>
  static T* create(ARGUMENTS&&... arguments);
};

class B : public A {
public:
  B();
};

void test() {
  B b;//compile error wanted here - but as a consequence of inheriting A
}

这里A是"library/framework"class。而 B 是 "user created class"。在 B 上要求 typedef 或类似的东西可能没问题。

更新:我在 A 上添加了 'create' 函数,我打算将其用于创建对象。

您可以在 A 的构造中要求一个仅在 A::create

的正文中传递的标记
#include <utility>

class A{
private:
  struct create_token
  { 
    create_token(const create_token &) = delete; 
    create_token& operator=(const create_token &) = delete; 
    create_token(create_token &&) = default; 
    create_token& operator=(create_token &&) = default; 
  };
protected:
  A(create_token) {}
public:
  template<class T, typename... ARGUMENTS>
  static T* create(ARGUMENTS&&... arguments)
  {
    // Whatever creation mechanism here
    return new T(create_token{}, std::forward<ARGUMENTS>(arguments)...);
  }
};

class B : public A {
public:
  template <typename Token> // Can't name A::create_token, it is private
  B(Token tok) : A(std::move(tok)) {}
  B(){} // Will always lack a `create_token`
};

int main() {
  B b;//compile error wanted here - but as a consequence of inheriting A
  B* b = A::create<B>();
}

See it live

这是另一种方法,它依赖于检查派生的 class 构造函数是否私有。但老实说,我更喜欢@Caleth

给出的解决方案
#include <type_traits>
#include <iostream>
#include <type_traits>


template<typename T, typename... Args>
struct constructor_tag{};



class A{
protected:


    template<typename T, typename... Args>
    A(constructor_tag<T, Args...>) {
        static_assert(!std::is_constructible_v<T, Args...>, "CONSTRUCTOR MUST NOT BE PUBLIC");
    };


public:
    template<class T, typename... ARGUMENTS>
    static T* create(ARGUMENTS&&... arguments) {
        return new T(std::forward<ARGUMENTS>(arguments)...);
    }
};

class B : public A {

    friend class A;
    B() : A(constructor_tag<B>{}) {}
public:
};

class C : public A {
    friend class A;

    C () : A(constructor_tag<C>{}) {}

    C(int) : A(constructor_tag<C, int>{}) {}
public:

};


// Following class will not compile because the constructor is public

//class D : public A {
//    friend class A;
//
//public:
//    D () : A(constructor_tag<D>{}) {}
//
//};

void test() {

    // B b; //calling a private constructor of class 'B'
    // C c(5);//calling a private constructor of class 'A'

    A::create<B>();
    A::create<C>(5);
    A::create<C>();
}

int main() {


    test();
}