传递 const char\* 作为模板参数

新手上路,请多包涵

为什么你不能在这里传递文字字符串?我做了一个非常轻微的解决方法。

 template<const char* ptr> struct lols {
    lols() : i(ptr) {}
    std::string i;
};
class file {
public:
    static const char arg[];
};
decltype(file::arg) file::arg = __FILE__;
// Getting the right type declaration for this was irritating, so I C++0xed it.

int main() {
    // lols<__FILE__> hi;
    // Error: A template argument may not reference a non-external entity
    lols<file::arg> hi; // Perfectly legal
    std::cout << hi.i;
    std::cin.ignore();
    std::cin.get();
}

原文由 Puppy 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

因为这不是一个有用的实用程序。由于它们不是模板参数的允许形式,因此它目前不起作用。

让我们假设它们有效。因为它们不需要为使用的相同值具有相同的地址,所以即使您的代码中具有相同的字符串文字值,您也会得到不同的实例化。

 lols<"A"> n;

// might fail because a different object address is passed as argument!
lols<"A"> n1 = n;

您可以为您的文本编辑器编写一个插件,用逗号分隔的字符文字列表替换字符串并返回。使用可变参数模板,您可以以某种方式“解决”这个问题。

原文由 Johannes Schaub - litb 发布,翻译遵循 CC BY-SA 2.5 许可协议

好问题,我想我会把帽子扔进戒指……我想你可以将指向静态变量的指针作为非类型模板参数传递。从 C++20 开始,它看起来不会成为问题……在此之前,这里有一些便宜的宏可以让它工作。

 template <const char *Name, typename T>
struct TaggedValue {
  static constexpr char const *name{Name};
  T value;
  friend ostream &operator<<(ostream &o, const TaggedValue &a) {
    return o << a.name << " = " << a.value;
  }
};

#define ST(name, type)\
  const char ST_name_##name[]{#name};\
  using name = TaggedValue<ST_name_##name,type>;

ST(Foo, int);
ST(Bar, int);
ST(Bax, string);

int main() {
  cout << Foo{3} << endl;
  cout << Bar{5} << endl;
  cout << Bax{"somthing"} << endl;
}

C++20 注释(编辑)

我最近很少使用 c++,所以如果这不是 100% 正确,我很抱歉。有一条关于为什么这在 c++20 中不会成为问题的评论。根据 template_parameters 上的参考资料:

非类型模板参数必须具有结构类型,该类型是以下类型之一(可选 cv 限定,限定符被忽略):

  • 浮点类型;
  • 具有以下属性的文字类类型:
    • 所有基类和非静态数据成员都是公共的和不可变的,并且
    • 所有基类和非静态数据成员的类型都是结构类型或其(可能是多维的)数组。

这使我相信以下代码会起作用:

 struct conststr
{
    const char * const p;
    template<std::size_t N>
    constexpr conststr(const char(&a)[N]) : p(a)/*, sz(N - 1) */{}
};

template<conststr s>
struct A{};

int main(int argc, char **argv) {
    A<conststr("foo")> x;
}

(同样,我不能 100% 确定这是否 100% 正确)。但它没有,至少在我的机器上没有 g++ -std=c++2ag++ --version == g++ (Debian 8.3.0-6) 8.3.0 )。它也不适用于 double这家伙 在这里对历史进行了更详细的描述,并且可能有更好的参考资料,我可能完全不正确。

原文由 Nathan Chappell 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题