2

我有:

class C 
{
    C(long){...};
    C(double){...};
    :
}

很遗憾,

C c{5}; // error! ambiguous overload

(这很可怕,不是吗?整数类型肯定有利于构造函数采用更高精度的整数参数。)

如何正确地将整数参数和浮点参数正确转发给各自的构造函数?

编辑:也许我过分简化了这个问题。它最初来自这个询问。我正在包装 Python 原语,例如 Float Long String,重要的是初始化被转发到正确的原语。同时,由于这是一个通用的包装器,我不希望消费者为了避免内部陷阱而担心类型转换。

正如 Mike Seymour 所指出的,SFINAE 提供了一种处理此问题的技术。

非常感谢 FreeNode C++ 频道上的 doug64k 提供以下解决方案:

http://ideone.com/QLUpu2 http://ideone.com/TCigR3 http://ideone.com/oDOSLH

明天当我找到线索时,我将尝试将这些作为答案。

4

3 回答 3

3

如何正确地将整数参数和浮点参数正确转发给各自的构造函数?

采用:

C c1{5L};
C c2{5.0};

这太可怕了,不是吗?整数类型肯定有利于构造函数采用更高精度的整数参数

该标准遵循一种算法来决定哪个重载函数是最佳匹配。除其他外,它对“促销”的排名高于“转化”。也就是说,“积分提升”排名高于“积分转换”,“浮点提升”排名高于“浮点转换”。但是,“积分转换”的排名不高于“浮点转换”这是第13.3.3.1.1 节标准转换序列中的表格

在此处输入图像描述

“积分提升”、“积分转换”、“浮点提升”和“浮点转换”可以在第4 节标准转换下使用的标准地址。出于此答案的目的,可以说 anint可以转换long notpromoted就足够了。Anint也可以转换double. 这就解释了为什么当参数类型为int.

于 2014-12-03T16:09:27.250 回答
2

我只是让它保持原样,让用户明确说明需要哪种类型转换。如果您真的想根据您描述的非标准规则允许隐式转换,您可以使用 SFINAE。像这样的东西会起作用:

#include <iostream>
#include <type_traits>

struct C {
    // Constructor for integer types
    template <typename T>
    C(T, typename std::enable_if<std::is_integral<T>::value, T>::type=0)
        {std::cout << "integral\n";}

    // Constructor for floating-point types
    template <typename T>
    C(T, typename std::enable_if<std::is_floating_point<T>::value, T>::type=0)
        {std::cout << "floating\n";}
};

int main() {
    C c1{5};   // prints "integral"
    C c2{5.0}; // prints "floating"
}

这种胡言乱语,以及那些习惯于通常的隐式转换规则的人的困惑,是否值得在显式转换中保存,这是一个见仁见智的问题。

于 2014-12-03T16:49:32.267 回答
1

您可以使用模板构造函数将未声明的类型重定向到您选择的构造函数。

假设您想long成为默认值。使用 SFINAE,您可以检查一个类型T是否能够转换为 a long,然后将其传递给 long 构造函数!

class C 
{
public:
    C(long l){ std::cout << "long constructor" << std::endl; };
    C(double d){std::cout << "double constructor" << std::endl; };

    // default constructor which passes values to long
    template <typename T, 
       typename std::enable_if<std::is_convertible<long, T>::value, int>::type = 0>
    C(T t) : C(long(t)){};
};


int main() {
    C c1(5);
    C c2(5.0f);
    C c3(5.0L);
    C c4(5.0);
    return 0;
}

这输出:

long constructor
long constructor
long constructor
double constructor
于 2014-12-03T16:51:36.970 回答