【问题标题】:Using std::enable_if to enable a templated constructor and a function that returns another templated instance使用 std::enable_if 启用模板化构造函数和返回另一个模板化实例的函数
【发布时间】:2017-04-05 14:16:18
【问题描述】:

我想创建一个模板类MyClass<T>,我想在其中有一个模板构造函数,它将接受MyClass<U> 类型的单个参数,只有当U 派生自T 时才有效(或与T 相同,在这种情况下本质上也充当复制构造函数)。如果不是,我想在编译时失败。此外,它还有第二个模板化成员函数MyClass<U> convert<U>() const,仅当U 派生自T(或与T 相同)时才有效。目前这些函数的实际实现并不重要,我现在只是想弄清楚如何声明它们。

虽然在某些情况下,可以使用 static_assertstd::is_base_of 而没有 std::enable_if 使编译失败,但我想知道是否可以使用 std:: enable_if。

提前致谢

【问题讨论】:

  • 那么问题是什么?通常enable_if 是您用来约束模板的东西。绑了还是不行?
  • 首先确保您了解静态断言和约束模板之间的区别。前者导致硬错误,后者使您的构造函数可检测。也就是is_constructible<MyClass<T>, Args...>这个问题有不同的答案,你需要先决定你想要什么样的行为。
  • 我一直试图从我在 Stroustrup 的 C++ 编程语言第 4 版中找到的示例中进行概括,但没有任何运气......我已经尝试了几种排列,我可以想到,使用std::is_base_of<T,U>std::enable_if,但到目前为止我没有尝试过。我正在使用 gcc 5.3,并使用 -std=c++11 进行编译,所以我应该可以使用 C++11 功能。

标签: c++ c++11 templates enable-if


【解决方案1】:

具有不同模板参数的类模板中的模板化构造函数

您将在这里遇到第一个要考虑的问题。 由于您无法明确指定构造函数的模板参数,因此必须从参数本身推导出来。

我自己试了一会儿,因为我很好奇,显然后面的代码不能工作:

class A {
    public:
        inline static std::string print() { return "A"; }    
};

class B 
    : public A {
    public:
        // Consciously hidden parent "print()"
        inline static std::string print() { return "B"; }
};

template <typename T>
class MyClass {
    public:

    explicit MyClass() {
        std::cout << "Default of MyClass with " << T::print() << std::endl;
    }

    template <typename U>
    MyClass(const typename std::enable_if<std::is_base_of<T, typename 
U::internal_type>::value, U>::type& other) {
        std::cout << "Copy constructor of equal or derived type!" << 
U::internal_type::print() << std::endl;
    }

    typedef T internal_type;
};

int main()
{ 
    MyClass<A> a;
    MyClass<B> b;
    MyClass<A> cpa(a);
    MyClass<A> cpb(b); // Error
}

重要的是:

template <typename U>
    MyClass(const typename std::enable_if<std::is_base_of<T, typename U::internal_type>::value, U>::type& other) {
        std::cout << "Copy constructor of equal or derived type!" << 
U::internal_type::print() << std::endl;
    }

我定义了 internal_type 帮助器来检查 MyClass with T = B 参数的 MyClass-template 参数,问题来了:

通常,我们从外部提供 U,没有它就不会做一些 enable_if 魔术。 在这种情况下,我们在没有任何信息的情况下传入 MyClass,但尝试从 U 中获取信息...

至少我现在通过尝试是这样理解的。

如果有效,该部分:

std::is_base_of<T, typename U::internal_type>::value

在我们的例子中将被替换为

std::is_base_of<A, B>::value

这应该是真的。 启用 if 依次应该取“U”,即 MyClass 并用它替换整个事物,相当于:

MyClass<A> {
    //...
    MyClass(const MyClass<B>& other) {
    }
};

所以我认为至少构造函数不可能如你所愿。

如果我错了并且需要了解更多信息,请模板元编程大师纠正我:D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-09
    • 2018-04-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    相关资源
    最近更新 更多