传递const char *作为模板参数

时间:2010-09-22 20:30:56

标签: c++ string templates

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

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();
}

5 个答案:

答案 0 :(得分:16)

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

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

lols<"A"> n;

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

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

答案 1 :(得分:6)

这是可能的,但模板参数必须具有外部链接,这排除了使用文字字符串并减轻了执行此操作的效用。

我的一个例子是:

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_>();

答案 2 :(得分:5)

我就是这样做的。对我来说更有意义:

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>();
}

答案 3 :(得分:1)

这适用于类,IMO非常有用。实施快速而肮脏,但可以很容易变得更干净:

#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(); }

输出:

真! 假! 真正! 假的!

答案 4 :(得分:0)

很好的问题,以为我会戴上帽子……我想您可以将指向静态变量的指针作为非类型模板参数传递。从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;
}