Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不是';在这种情况下,是否调用了最合适的构造函数?_C++_Constructor_Type Conversion_Copy Constructor_Enable If - Fatal编程技术网

C++ 为什么不是';在这种情况下,是否调用了最合适的构造函数?

C++ 为什么不是';在这种情况下,是否调用了最合适的构造函数?,c++,constructor,type-conversion,copy-constructor,enable-if,C++,Constructor,Type Conversion,Copy Constructor,Enable If,考虑以下类别: class-foo{ int数据; 公众: 模板 foo(const T&i):数据{i}{cout之所以发生,是因为操作符int() 由于operator int(),obj1调用operator int(),并将自身转换为int 可能的解决办法: 使用static\u cast。这将把通常应转换为int的变量转换为foo 任何人请编辑这个问题,并填写这个。我没有更多的想法 您的模板“move”构造函数(带有T=foo&)有一个foo&类型的参数,它比您的复制构造函数更匹配,

考虑以下类别:

class-foo{
int数据;
公众:
模板

foo(const T&i):数据{i}{cout之所以发生,是因为
操作符int()

由于
operator int()
obj1
调用
operator int()
,并将自身转换为
int


可能的解决办法:

  • 使用
    static\u cast
    。这将把通常应转换为
    int
    的变量转换为
    foo

  • 任何人请编辑这个问题,并填写这个。我没有更多的想法

  • 您的模板“move”构造函数(带有
    T=foo&
    )有一个
    foo&
    类型的参数,它比您的复制构造函数更匹配,因为它只需要
    const foo&
    。然后,您的模板构造函数通过将
    i
    转换为
    int
    ,调用
    操作符int()

    最简单的即时修复方法是使用
    enable_if
    来限制移动构造函数移动操作:如果
    T
    被推断为左值引用类型(意味着你的
    T&&i
    也将塌陷为左值引用),则强制替换失败

    template <typename T, typename = enable_if_t<is_constructible<int, T>::value>,
                          typename = enable_if_t<!is_lvalue_reference<T>::value>>
    foo(T&& i) : data( std::move(i) ) { cout << "Value move ctor" << endl; }
    
    这将替换您的值复制和值移动构造函数


    另一个注意事项:
    is_constructible::value
    是一个测试,它告诉您
    数据(std::forward(i))
    是否格式正确。它不测试
    数据{std::forward(i)}
    格式良好。结果不同的
    T
    long
    ,因为
    long
    int
    的转换是窄化转换,并且
    {}中不允许窄化转换

    它是否应该是可构造的,而不是像您现在所拥有的那样是可构造的?@Alejandro,这也是正确的。@nwp我很困惑。根据,该东西返回第一个东西是否可以从第二个东西构造。由于我正在构造我的
    数据
    成员(它是
    int
    )从
    T
    参数来看,这应该是正确的顺序。我只接受可以从中构造
    int
    的类型。您所说的确实解决了问题,但我现在比以前更困惑了:dwat@Alejandro所说的只起作用,因为在示例中T是int。如果您将数据声明为任何非原始类型(称之为酒吧)而int不能从bar中构造,那么这些构造函数将被排除在is_constructible之外,因为对于t:int,int没有从bar中构造自身的可见方法。但是,如果bar声明一个接受int的公共构造函数,那么t:int的is_constructible将成功。如果我错误地解释了用法,请纠正我。什么@alejandro说的也是真的。我知道为什么可能,但问题是为什么会这样。因为有一个构造函数接受参数的确切类型(
    foo
    ),不应进行转换。如果类没有接受
    foo
    对象的构造函数,这将是完全正常的,但既然它接受了,那么这应该是一个比触发转换更简单的途径。此外,
    static\u cast
    也不能解决问题。我传入的值已经是
    foo类型,不需要强制转换它。那么也许您可以生成一个
    操作符foo()
    所以我的问题是,我将
    foo
    对象传递给一个函数,该函数确实有一个重载,用于
    foo
    参数,但这不是被调用的重载。呃,我真的很困惑。这似乎是一个可能的解决方案,但我不确定你的意思。你能解释得更好一点吗?这很有效!我不知道右值引用可以以任何方式折叠为左值引用。谢谢!您添加的其他内容也非常有用。我没有想到其中的一些内容。谢谢我刚才看了talk…现在一切都有意义:)Herb在演讲的最后一节中谈到了完美的转发
    T&
    。我希望我能早点看这个。
    template <typename T, typename = enable_if_t<is_constructible<int, T>::value>
                        , typename = enable_if_t<!is_same<decay_t<T>, foo>::value>
    foo(T&& i) : data( std::forward<T>(i) ) { cout << "Forwarding ctor" << endl; }