Ðаn*_*Ðаn 6 c++ macros templates
我试图找到一种方法来减少一些语法"噪音"而不诉诸宏.对于以下代码:
struct base { base() = delete; };
struct tag1 final : private base
{
static constexpr const char* name = "tag1";
};
template <typename T> std::string name() { return T::name; }
// ...
int main()
{
const std::string name1(name<tag1>());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这将是很好摆脱的一些static constexpr const char*(更不用提其他)语法,因为它很烦人的重复,对tag2,tag3等等.另外,所有的这是非常有趣的是唯一的一部分tag1,其余的是"噪声".直接的解决方案是使用宏:
#define MAKE_TAG(tag_name) struct tag_name final : private base { \
static constexpr const char* name = #tag_name; }
MAKE_TAG(tag2);
// ...
const std::string name2(name<tag2>());
Run Code Online (Sandbox Code Playgroud)
基于宏的MAKE_TAG(tag2);语法已经消除了所有"噪音",tag2非常突出.宏的一个额外好处是tag_name可以很容易地将其转换为字符串文字,以防止复制粘贴错误.
template<const char* name> base { ... };
struct tag3 final : private base<"tag3"> {};
Run Code Online (Sandbox Code Playgroud)
但是C++不支持.从下面的答案中,巧妙的解决方法是使用可变参数模板:
template<char... S> struct base { base() = delete;
static std::string name() { return{ S... }; } };
struct tag4 final : base<'t', 'a', 'g', '4'> { };
template <typename T> std::string name() { return T::name(); }
Run Code Online (Sandbox Code Playgroud)
这确实减少了很多噪音,但需要写't', 'a', 'g', '4'而不是"tag4".运行时解决方案相当简洁
struct base {
const std::string name;
base(const std::string& name) : name(name) {} };
struct tag5 final : base { tag5() : base("tag5") {} };
template <typename T> std::string name() { return T().name; }
Run Code Online (Sandbox Code Playgroud)
但这并不完全令人满意,因为tag5现在可以实例化,理想情况下没有意义.此外,现在需要写tag5三次,这不是很干.
有没有办法进一步简化(即减少打字)上面的代码?...没有使用宏?
如果您愿意单独输入字符,我们可以执行以下操作:
template<char... S>
struct base {
base() = delete;
static std::string name(){
return {S...};
}
};
struct tag1 final : private base<'t','a','g','1'>
{using base::name;};
struct tag2 final : private base<'t','a','g','2'>
{using base::name;};
Run Code Online (Sandbox Code Playgroud)
像这样称呼它:
std::cout << tag1::name() << std::endl;
std::cout << tag2::name() << std::endl;
Run Code Online (Sandbox Code Playgroud)
我必须添加using base::name派生类,因为您使用的是私有继承。如果继承变成protectedor public,那么你就不需要它。
name()基础函数的要点是创建一个字符数组,我们可以从中构造一个字符串。我们使用可变参数包扩展来创建数组。
| 归档时间: |
|
| 查看次数: |
172 次 |
| 最近记录: |