【问题标题】:forcing templatized constructor over compiler generated copy-constructor在编译器生成的复制构造函数上强制模板化构造函数
【发布时间】:2016-07-28 23:16:14
【问题描述】:

采取以下,

template<class T>
struct Foo {
    Foo(){}

    // a template constructor "generalized" over related types
    template<class U>
    Foo(Foo<U> const&) {
        std::cout << 1;
    }

    // copy constructor
    Foo(Foo const&) {
        std::cout << 2;
    }
};

及其用户:

void main() {
   Foo<int> f1;
   Foo<const int> f2(f1); // prints 1
   Foo<const int> f3(f2); // prints 2
}

即使没有显式复制构造函数,编译器也会生成一个并将其用于f3(f2)

有没有办法强制模板重载?例如,复制构造函数可以被 SFINAE 淘汰吗?这是为了避免代码重复,因为有趣的是,似乎也没有办法使用委托构造函数(从复制构造函数委托给模板构造函数)。

【问题讨论】:

  • 不,这不一样,它会呈现f3(f2) 一个错误,因为重载决议仍然选择复制构造函数并错误输出为deleted。 (我回复的评论是询问delete 是否是一个选项)

标签: c++ templates c++11 constructor


【解决方案1】:

构造函数模板永远不能是复制构造函数,所以如果你不定义一个,编译器会隐含地为你做,正如你所发现的那样。

避免代码重复的一种解决方法是定义第三个构造函数并从上面显示的两个构造函数委托给它。

template<class T>
struct Foo {
    Foo(){}

    struct tag{};

    // a template constructor "generalized" over related types
    template<class U>
    Foo(Foo<U> const& f)
    : Foo(tag{}, f)
    {
        std::cout << 1 << '\n';
    }

    // copy constructor
    Foo(Foo const& f) 
    : Foo(tag{}, f)
    {
        std::cout << 2 << '\n';
    }

private:
    template<class U>
    Foo(tag, Foo<U> const&)
    {
        std::cout << 3 << '\n';
    }
};

Live demo

【讨论】:

  • 有趣的建议。实际上很好地解决了实际用例。但是,这不是对“可以禁用复制构造函数”问题的直接答案(正在寻找具有默认 sfinaed 参数等的非隐式版本 - 也许答案是否定的)。我想在这一点上没有实际意义....
  • @sly 我不明白你如何可以 SFINAE 禁用复制构造函数。它不是模板,因此不涉及扣除,这是 SFINAE 启动所必需的。
猜你喜欢
  • 1970-01-01
  • 2011-05-24
  • 2017-07-20
  • 2016-09-12
  • 1970-01-01
  • 1970-01-01
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多