代码之家  ›  专栏  ›  技术社区  ›  Puppy

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

  •  26
  • Puppy  · 技术社区  · 14 年前

    为什么不能在这里传递字符串?我做了一个很小的变通。

    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();
    }
    
    4 回复  |  直到 6 年前
        1
  •  15
  •   Johannes Schaub - litb    14 年前

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

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

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

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

        2
  •  6
  •   Nathan Ernst    11 年前

    这是可能的,但是template参数必须具有外部链接,这会阻止使用文本字符串,并降低执行此操作的实用性。

    我举了一个例子:

    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_>();
    
        3
  •  5
  •   Michael    9 年前

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

    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>();
    }
    
        4
  •  0
  •   Ben Earhart    6 年前

    这适用于班级,在我看来是有用的。该实现既快速又脏,但很容易变得更干净:

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

    输出:

    真的! 错了! 真的! 错了!