c++ - 通用 vector 类中的重载解析问题

标签 c++ templates c++11 generics lambda

我有一个通用 vector 类,其中我实现了一个接受仿函数的构造函数。这个想法是调用仿函数来初始化 vector 中的每个元素,仿函数的单个参数是元素索引。

但是,当传递与 vector 元素类型不同类型的标量时,这会干扰我的“来自标量”构造函数:

template <typename T, int N>
struct SomeVectorClass
{
    T values[N];

    SomeVectorClass() {}

    SomeVectorClass(T scalar)
    {
        for (int i = 0; i < N; i++) values[i] = scalar;
    }

    template <typename InitFunctionType>
    SomeVectorClass(InitFunctionType initFunction)
    {
        for (int i = 0; i < N; i++) values[i] = initFunction(i);
    }
};

...

SomeVectorClass<int, 2> a([&] (int i) { return i; }); // This works
SomeVectorClass<int, 2> b(123); // This works
SomeVectorClass<int, 2> c(123.f); // This causes error "called object type 'float' is not a function or function pointer"

我对 c 的期望是编译器自动将 123.f 转换为 123,然后调用“来自标量”构造函数(在本例中接受 int)。

三个问题:

  1. 重载决策是否首选 lambda 构造函数,因为它不需要强制转换?
  2. 有没有办法在没有 std::enable_if 或类似黑客的情况下完成这项工作?
  3. 如果不是,如果 InitFunctionType 是仿函数,我将如何使用 std::enable_if 仅启用仿函数构造函数?

预先感谢您的宝贵时间!

编辑:忘记提及,出于性能原因,我无法使用 std::function。该类需要内联友好。

最佳答案

构造函数模板是首选,因为它是精确匹配,而 T构造函数需要转换。首选精确匹配。

这正是 enable_if 所遇到的问题。存在来解决。您需要从重载决策集中删除构造函数模板,除非它实际上可以使用 int 进行调用。 :

template <typename F,
          typename = typename std::result_of <F(int)>::type>
SomeVectorClass (F func) { }

这样,就可以使用 float 进行构建或char将选择您的T构造函数。这是唯一的候选人!

注意:std::result_of不一定是 SFINAE 友好的 ( N3462 )。上面的代码适用于 gcc 4.9.2,但不适用于 gcc 4.7.2。如果上面无法编译,类似

include/c++/4.7.2/type_traits:1834:9: error: ‘std::declval<float>()’ cannot be used as a function

然后你可以将“仿函数”构造函数重写为:

template <typename F,
          typename = decltype(std::declval<F>()(std::declval<int>()))
SomeVectorClass (F func) { }

关于c++ - 通用 vector 类中的重载解析问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29966780/

相关文章:

C++:根据模板参数填充数组

c++11 - 如何使用旧的 ABI 通过 GCC 5 编译 boost?

c++ - C++11 中的随机字节生成

c++ - 如何比较 C++ 中的泛型结构?

c++ - 为什么 *= 运算符没有按我预期的方式运行?

c++ - 使用 GDB 调试模板

c++ - QT对话框关闭和删除

模板类的 C++ 转换

c++ - C++ 中变量的默认值使用 cin >>

c++ - 为什么允许部分模板特化?