SFINAE:确定抽象类是否具有不可访问的默认构造函数

时间:2017-06-05 04:17:26

标签: c++ templates constructor private sfinae

我需要在编译时确定抽象类T(作为模板参数传入)是否具有受保护或私有无参数构造函数。因为T是抽象的,所以std::is_constructible<T>系列的所有版本都会返回false。

我尝试定义一个继承自相关类的类U,具有using T::T,并具体;不幸的是,我发现using指令忽略了默认的构造函数;

(我需要这个用于SFINAE目的;我需要使我的模板化具体版本的T工厂拒绝使用显式无法访问的构造函数的T。)

这就是我想要实现的目标:

#include <iostream>
#include <utility>

template <typename T, typename... Args>
static T* make(Args&&...);

class Base {
    public:
        void ImportantFunctionThatRequiresFactorySupport();

    private:
        class InstantiationToken {};
        virtual InstantiationToken* NoInstantiationForYou() = 0;

        template <typename T>
        class Deabstractifier final : public T {
            private:
                InstantiationToken* NoInstantiationForYou() { return NULL; }
        };

    template <typename T, typename... Args>
    friend T* make(Args&&...);
};

template <typename T, typename... Args>
static T* make(Args&&... args) {
    // There should be a static_assert here to detect when T has a protected constructor and refuse to make one
    return new Base::Deabstractifier<T>(std::forward<Args>(args)...);
}

class IntermediateDerivedThatIsFineToConstruct : public Base {
    public:
        IntermediateDerivedThatIsFineToConstruct() = default;

        void DoSomethingOrdinaryAndCompletelyReasonable() {
            ImportantFunctionThatRequiresFactorySupport();
        }
};

class IntermediateDerivedThatShouldOnlyBeInheritedFrom : public Base {
    protected:
        IntermediateDerivedThatShouldOnlyBeInheritedFrom() = default;

    public:
        void SomethingElseCompletelyReasonable() {
            ImportantFunctionThatRequiresFactorySupport();
        }
};

class ThingThatShouldBeConstructibleAgain : public IntermediateDerivedThatShouldOnlyBeInheritedFrom {
    public:
        void SomeExtaFunctionality() {};
};


int main()
{
    std::cout << "Starting..." << std::endl;
    make<IntermediateDerivedThatIsFineToConstruct>(); // Should succeed
    std::cout << "Did thing 1" << std::endl;
    make<ThingThatShouldBeConstructibleAgain>(); // Should succeed
    std::cout << "Did thing 2" << std::endl;
    make<IntermediateDerivedThatShouldOnlyBeInheritedFrom>(); // Should fail at compile time
    std::cout << "Did thing 3" << std::endl;
}

live on coliru

0 个答案:

没有答案