MSP430 GCC 是否支持更新的 C++ 标准? (比如 11、14、17)
Does MSP430 GCC support newer C++ standards? (like 11, 14, 17)
我正在编写一些代码,这些代码将极大地受益于随 C++ 11 引入的 lambda 的简洁语法。编译器支持吗?
使用 Energia 或 embedXcode 编译时如何指定编译器标志?
TI 网站上关于此主题的内容不多,或者,至少,我对 C++ 的了解还不够多,无法为您提供详细而准确的答复。
this document that is mainly a derivation of the Itanium C++ ABI 中描述了嵌入式 ABI 的实现。它没有解释 lambda 的实现,也没有解释 auto
关键字(或者我可能无法从文档中获取此信息)。
于是决定直接在Energia测试。显然 g++
版本是 4.6.3,因此它应该支持两者。
事实上(从编译的角度来看,我这里没有我的 MSP 来测试代码)它可以编译如下内容:
// In template.hpp
#ifndef TEMPLATE_HPP_
#define TEMPLATE_HPP_
template<class T>
T func(T a) {
auto c = [&](int n) { return n + a; };
return c(0);
}
#endif /* TEMPLATE_HPP_ */
// in the sketch main
#include "template.hpp"
void setup() { int b = func<int>(0); }
void loop() { }
(模板仅在 header 中有效,在主草图中引发错误)。为了编译这个草图,我不得不修改编辑器的一个内部文件。最大支持的标准好像是-std=c++0x
,编译标志在文件里:
$ENERGIA_ROOT/hardware/energia/msp430/platform.txt
在我的设置中,根位于 /opt/energia
。在该文件中,我修改了 32
(compiler.cpp.flags
) 行并添加了该选项。请注意 -std=c++11
不受支持(引发错误)。
compiler.cpp.flags=-std=c++0x -c -g -O2 {compiler.mlarge_flag} {compiler.warning_flags} -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD
不幸的是,我对 embedXcode 的经验为零:\
模仿std::function
未提供 std::function
,因此您必须编写某种模仿它的 class。类似于:
// callback.hpp
#ifndef CALLBACK_HPP_
#define CALLBACK_HPP_
template <class RET, class ARG>
class Callback {
RET (*_f)(ARG);
public:
Callback() : _f(0) { };
Callback(RET (*f)(ARG)) : _f(f) { };
bool is_set() const { return (_f) ? true : false; }
RET operator()(ARG a) const { return is_set() ? _f(a) : 0; }
};
#endif /* CALLBACK_HPP_ */
// sketch
#include "callback.hpp"
// | !! empty capture!
void setup() { // V
auto clb = Callback<int, char>([](char c) { return (int)c; });
if (clb.is_set())
auto b = clb('a');
}
void loop() {}
可以完成这项工作,它使用一个简单的技巧:
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. [C++11 standard 5.1.2]
只要您将捕获留空,就可以确保 "conversion" 指向函数指针,因此您可以毫无问题地存储它。我写的代码:
- 需要作为返回类型的第一个模板
RET
- 需要第二个模板
ARG
,它是回调的一个参数。在大多数情况下,您可能会考虑使用 void*
作为通用参数(将结构指针转换为 void 指针并将其用作函数中的 counter-cast 的参数,该操作无需任何费用)
- 实现两个构造函数:空构造函数将函数指针初始化为
NULL
,而第二个直接分配回调。注意缺少拷贝构造函数,需要自己实现。
- 实现调用函数的方法(重载运算符
()
)并检查回调是否实际存在。
再一次:这些东西编译时没有警告,但我不知道它是否适用于 MSP430,因为我无法测试它(它适用于常见的 amd64 linux系统).
截至 2018 年 2 月,最高支持 C++14,但有一些限制:
http://processors.wiki.ti.com/index.php/C%2B%2B_Support_in_TI_Compilers
我正在编写一些代码,这些代码将极大地受益于随 C++ 11 引入的 lambda 的简洁语法。编译器支持吗?
使用 Energia 或 embedXcode 编译时如何指定编译器标志?
TI 网站上关于此主题的内容不多,或者,至少,我对 C++ 的了解还不够多,无法为您提供详细而准确的答复。
this document that is mainly a derivation of the Itanium C++ ABI 中描述了嵌入式 ABI 的实现。它没有解释 lambda 的实现,也没有解释 auto
关键字(或者我可能无法从文档中获取此信息)。
于是决定直接在Energia测试。显然 g++
版本是 4.6.3,因此它应该支持两者。
事实上(从编译的角度来看,我这里没有我的 MSP 来测试代码)它可以编译如下内容:
// In template.hpp
#ifndef TEMPLATE_HPP_
#define TEMPLATE_HPP_
template<class T>
T func(T a) {
auto c = [&](int n) { return n + a; };
return c(0);
}
#endif /* TEMPLATE_HPP_ */
// in the sketch main
#include "template.hpp"
void setup() { int b = func<int>(0); }
void loop() { }
(模板仅在 header 中有效,在主草图中引发错误)。为了编译这个草图,我不得不修改编辑器的一个内部文件。最大支持的标准好像是-std=c++0x
,编译标志在文件里:
$ENERGIA_ROOT/hardware/energia/msp430/platform.txt
在我的设置中,根位于 /opt/energia
。在该文件中,我修改了 32
(compiler.cpp.flags
) 行并添加了该选项。请注意 -std=c++11
不受支持(引发错误)。
compiler.cpp.flags=-std=c++0x -c -g -O2 {compiler.mlarge_flag} {compiler.warning_flags} -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD
不幸的是,我对 embedXcode 的经验为零:\
模仿std::function
std::function
,因此您必须编写某种模仿它的 class。类似于:
// callback.hpp
#ifndef CALLBACK_HPP_
#define CALLBACK_HPP_
template <class RET, class ARG>
class Callback {
RET (*_f)(ARG);
public:
Callback() : _f(0) { };
Callback(RET (*f)(ARG)) : _f(f) { };
bool is_set() const { return (_f) ? true : false; }
RET operator()(ARG a) const { return is_set() ? _f(a) : 0; }
};
#endif /* CALLBACK_HPP_ */
// sketch
#include "callback.hpp"
// | !! empty capture!
void setup() { // V
auto clb = Callback<int, char>([](char c) { return (int)c; });
if (clb.is_set())
auto b = clb('a');
}
void loop() {}
可以完成这项工作,它使用一个简单的技巧:
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. [C++11 standard 5.1.2]
只要您将捕获留空,就可以确保 "conversion" 指向函数指针,因此您可以毫无问题地存储它。我写的代码:
- 需要作为返回类型的第一个模板
RET
- 需要第二个模板
ARG
,它是回调的一个参数。在大多数情况下,您可能会考虑使用void*
作为通用参数(将结构指针转换为 void 指针并将其用作函数中的 counter-cast 的参数,该操作无需任何费用) - 实现两个构造函数:空构造函数将函数指针初始化为
NULL
,而第二个直接分配回调。注意缺少拷贝构造函数,需要自己实现。 - 实现调用函数的方法(重载运算符
()
)并检查回调是否实际存在。
再一次:这些东西编译时没有警告,但我不知道它是否适用于 MSP430,因为我无法测试它(它适用于常见的 amd64 linux系统).
截至 2018 年 2 月,最高支持 C++14,但有一些限制: http://processors.wiki.ti.com/index.php/C%2B%2B_Support_in_TI_Compilers