【问题标题】:Having a template compile for only known execution path仅针对已知执行路径编译模板
【发布时间】:2018-03-25 21:02:29
【问题描述】:

在下面的示例中,尽管我知道已知的执行路径将是“安全的”,但我在编译它时遇到了问题。 “安全”是指我知道我只会以这种方式使用它。有没有一种算法或更好的方法来构建一个场景,即使我知道我永远不会有一个“类型”的“浮点”传递一个“种类”值为 1?

我得到的特别错误是

error C2248: 'foo::foo' : cannot access private member declared in class 'foo'

测试用例示例

#include <vector>
using namespace std;

class foo {
private:
    foo(float val) {
        val = 99.0f;
    }
public:
    foo(int val) {
        val = 2;
    }
};

template<typename Type>
struct bar {
public:
    vector<Type> array;

    void Add(Type value) {
        array.push_back(value);
    }
};

class bunny {
    bar<float> floats;
    bar<foo> foos;
public:
    template<typename Type>
    void Initialize(int kind, Type value) {
        if(kind == 0)
            floats.Add(value);
        else if(kind == 1)
            foos.Add(value);
    }
};

int main(void) {
    bunny first; first.Initialize(0, 1.0f);
    //bunny second; second.Initialize(1, 0);

    return 0;
}

【问题讨论】:

  • 有一个关键字friend可能对你有帮助。
  • 我假设您故意将 foo(float) 构造函数设为私有以测试编译器是否使用它?无论如何,我认为您可以使用 Initialize() 方法的专业化来做您想做的事情。
  • @JorgeGonzálezLorenzo 我从未听说过诸如 Initialize() 方法的“专业化”之类的东西。那该怎么做呢?
  • kind 参数的用途是什么?如果它只是说明你有什么类型的value,那么有更好的方法(使用类型系统)来做到这一点。
  • 在上面的代码中,我认为根本不需要kind。我可以告诉编译器从值的类型中推断出哪个分支。你可以消除善良吗?或者如果你无缘无故地弄错了,我必须编写 UB 的代码吗?

标签: c++ arrays algorithm templates


【解决方案1】:

在 C++ 中,您可以拥有多个具有相同名称但参数数量或类型不同的函数,例如,您可以拥有两个函数:

void foo(float a)
{
    std::cout << "Float!" << a << std::endl;
}
void foo(int a)
{
    std::cout << "Int!" << a << std::endl;
}

如果您调用这些函数之一,编译器将根据您为函数提供的参数推断要调用的函数。 这就是函数重载。

在你的情况下,你可能会将你的兔子类重写为这样的:

class bunny {
    bar<float> floats;
    bar<foo> foos;
public:
    void Initialize(foo value) {
        foos.Add(value);
    }
    void Initialize(float value) {
        floats.Add(value);
    }
};

如果你调用first.Initialize(1.0f),编译器知道他需要调用void Initialize(float value),因为你传递了一个浮点数给函数。

【讨论】:

  • 我想使用模板,因为除了“初始化”之外,可能还有许多“条形”列表和其他功能。我这里只展示一个函数作为最小的测试用例。
  • 由于每个“条形”列表都有不同的名称,因此您需要为每个列表编写特定的代码。您可以制作条形静态模板(template&lt;typename T&gt; static bar&lt;T&gt; barObject;,这称为变量模板,从 C++14 开始工作)并使用此函数:template&lt;typename T&gt; void Initialize(T value){ bar&lt;T&gt;.Add(value); }。但是,您将无法使用模板成员(非静态)变量。您可以尝试模拟它们:stackoverflow.com/a/49397130/6860744 但这可能不值得。
猜你喜欢
  • 2022-01-14
  • 2016-06-26
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-13
  • 2022-01-11
相关资源
最近更新 更多