Passing const char * as a template argument

Why can't you pass literary lines here? I did this with very little workaround.

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(); } 
+26
c ++ string templates
Sep 22 '10 at 20:30
source share
5 answers

Because it will not be a useful utility. Since they are not a valid form of a template argument, it does not currently work.

Suppose they work. Since they don’t need to have the same address for the same value, you will get different instances, even if the code has the same string literal value.

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

You can write a plug-in for a text editor that replaces the string with a comma-separated list of characters and vice versa. With variation patterns, you could "solve" this problem in this way, in some way.

+16
04 Oct '10 at 11:54 on
source share

Perhaps, but the template argument should have an external connection, which eliminates the use of literals and mitigates the usefulness of this.

An example that I have:

 template<const char* name, const char* def_value=empty_> struct env : public std::string { env() { const char* p = std::getenv(name); assign(p ? p : def_value); } }; extern const char empty_[] = ""; std::string test = env<empty_>(); 
+6
May 6 '13 at 16:04
source share

This is how I do it. It makes a lot more sense to me:

 struct MyString { static const std::string val; } const std::string MyString::val = "this is your string"; template<typename T> void func() { std::cout << T::val << std::endl; } void main() { func<MyString>(); } 
+5
Nov 03 '15 at 17:56
source share

This works for classes and, IMO, is useful. The implementation is quick and dirty, but it is easy to make it cleaner:

 #include <stdio.h> #include <string.h> struct TextTag { const char *text; }; template <const TextTag &TRUE, const TextTag &FALSE> struct TextTaggedBool { const char *GetAsText() const { return m_value ? TRUE.text: FALSE.text; } void SetByText(const char *s) { m_value = !strcmp(s, TRUE.text); } bool m_value; }; class Foo { public: void method() { m_tbool.SetByText("True!"); printf("%s\n", m_tbool.GetAsText()); m_tbool.SetByText("False!"); printf("%s\n", m_tbool.GetAsText()); m_tbool.m_value = true; printf("%s\n", m_tbool.GetAsText()); m_tbool.m_value = false; printf("%s\n", m_tbool.GetAsText()); } private: static constexpr TextTag TrueTag = { "True!" }; static constexpr TextTag FalseTag = { "False!" }; TextTaggedBool<TrueTag, FalseTag> m_tbool; }; void main() { Foo().method(); } 

Exit:

Truth! Lying! Truth! Lying!

+1
Mar 17 '18 at 15:26
source share

Good question, I thought, I would throw my hat in the ring ... I think you can pass pointers to static variables as arguments of the template type. With C ++ 20, it doesn't seem like it will be a problem ... In the meantime, here are a few cheap macros to make it work.

 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; } 
0
May 27 '19 at 11:34
source share



All Articles