从文件中获取模板参数
Get template parameter from file
我有两个类:
- 非类型模板类Foo
- 一个非模板类Bar,它包含Foo的一个成员,其中的模板参数应该从文件中读取
据我所知,这不起作用,因为非模板化类的模板参数是在编译时设置的,所以它们需要是静态常量。我不知道如何实现这一点,因为在我提供参数值之前,必须进行一些评估(即读取文件、提取值)。尽管如此,有没有办法实现类似的目标?
我希望避免模板化第二个类,因为用户(理论上)不知道该文件,应该在执行程序时查找该文件。该文件在运行时不会更改。
因此,情况是这样的:
// templated class
template <int A>
class Foo {
public:
Foo() : A_(A) {};
void print () { std::cout << "The value of A is : " << A_ << std::endl; }
private:
int A_;
};
// non-templated class
// This won't work, just showing the idea:
class Charlie {
public:
Charlie() {
A = loadFromFile("myfile");
}
void print () {
std::cout << "Called from C: " << std::endl;
C_.print();
}
private:
int A;
Foo<A> C_;
};
谢谢!
您不能从文件中读取模板参数,也不能在运行时以其他方式确定。
模板参数,本质上需要在编译时推导/计算。别无选择,对不起!
模板参数的思想是,它们可以在编译时进行优化,因此不能推迟到运行时解决。
在您的示例中,答案很简单。使Foo
不是模板。
Foo
在您的案例中作为模板没有任何好处。
从表面上看,这似乎是对你的问题的法律误读,它触及了问题的核心。您可以重构代码中在运行时发生变化的部分,而这些部分不是模板参数。您正在从文件中读取一个int:它是一个运行时参数。您可以通过接口、类型擦除等方式在编译时和运行时完成大部分可以完成的工作。理论上,你可以构建一个与编译时一样强大的运行时类型系统,但我们称之为一种新语言。)
编译时模板为您提供了对编译时所知内容的检查,并提供了一些优化机会(编译时已知更多)和安全性(同上)。
当您不知道模板参数的值、范围或任何东西时,这些检查都是没有意义的,因此是不必要的。使参数成为运行时参数,而不是编译时参数。
你正在做的事情的一个具体例子可以带来一个具体的解决方案。
struct Foo {
Foo(int A) : A_(A) {};
void print () {
std::cout << "The value of A is : " << A_ << std::endl;
}
int A_;
};
struct Charlie {
Charlie():C_{loadFromFile("myfile")}{}
void print () {
std::cout << "Called from C: " << std::endl;
C_.print();
}
Foo C_;
};
这与你要求的行为完全匹配。不是你要求的方式,但考虑到实际问题,这种方式毫无意义。
"魔术开关"可以用于从运行时调度到编译时代码。双重调度更为棘手,因为它是在运行时进行的,您需要类似的折衷方案。类型擦除(如sts::function
)允许您将状态需求抽象到行为类似"相同"类型的干净接口中。生成的跳转表保持低成本。
不幸的是,C++元编程能力对于这种进程来说太弱了。
虽然你的要求没有错(即使用真正的工具(如打开文件和读取一些数据)进行编译时计算),但这在当前(以及IMO和未来)C++中是完全不可能的。
此外,在您的示例中,您似乎需要在运行时读取值,并且仍在考虑编译时和运行时的独立阶段。我能想到的避免在"运行时"生成代码的唯一解决方案是将Bar
作为基类,并为您需要传递的数字的所有可用值预先实例化派生类。这样,您就可以选择特定的派生类在运行时实例化。然而,请注意,这很可能是C++的一个无意义的解决方案,如果尝试这样做,也会有严重的代码膨胀风险。
然而,在C++中,即使操作需要在编译时进行,也不可能读取文件,并且您不要求在运行时生成代码。
要解决这类元编程问题,唯一的解决方案是从单独的程序生成代码。我个人发现Python是生成C++的一个很好的工具,但任何具有一定文本处理能力的语言都可以做到这一点。
C++元编程只是关于模板,即"愚蠢"地替换函数和类骨架。由于某些原因,添加了一些功能,再加上该语言极其复杂的语法规则,恰好为这种非常原始的方法带来了(IMO非自愿的)图灵完整性。
这本身并不坏,但不幸的是,由于一些奇怪的心理影响(对我来说无法解释),这也意味着任何增加真正元编程能力的尝试都被放弃了,取而代之的是,所有C++大师都继续试验这个错误构建的新玩具。
您可以使用递归来模拟循环,使用SFINAE和专门化来模拟条件,使用递归类型列表来模拟数据结构。。。他们还难以置信地强调了编译器,并获得了例如提高模板实例化递归堆栈的能力,以便能够做更多的技巧。
这种对无意义谜题的热爱指导了所有"现代"C++对元编程的研究,因此,几十年后,我们仍然无法在编译时(甚至在运行时…C++也没有反射,因为这些人还没有找到使用SFINAE模拟的方法)完成琐碎的任务,比如从文件中读取或枚举类的成员。
您在标准库中有编译时有理算术,但是。。。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 有没有办法在从编译器获取参数时避免预处理器宏?
- C++ - 声明指向返回任何类型并获取任意数量参数的函数的指针
- 如何从参数中获取函数签名?
- 获取可变参数模板参数包的相关类型
- 在 C++11 中获取函子作为参数
- 如何使用可变参数模板获取参数的变量号及其大小C++
- 是否可以获取成员函数模板参数的拥有对象?
- 如何从 x64 程序集中的堆栈中获取参数?
- 获取第一个模板参数的可靠方法
- 如何从参数包获取指向对象的指针
- C++ 如何使派生类自动获取基类参数
- 通过命令行参数获取llvm ir文件时面临问题
- 在C++中,是否允许将函数指针强制转换为将指向基类或派生类的指针作为参数获取的函数指针
- 使用一个可选参数获取两个参数到main
- cpp 映射作为函数参数获取警告信息 "discards qualifiers"
- 从控制台应用中的命令行参数获取文件名C++
- 从模板参数获取函数参数
- 使用参数获取其他参数