簡體   English   中英

字符串 class 構造函數接受 const char* 列表

[英]String class constructor accepting list of const char*

在我的字符串 class 中,我想制作一個接受可變長度 arguments ( const char* ) 的 ctor,例如帶有可變參數模板的參數包。

像下面這樣的東西

class String
{
public: 
    
    String(const char*... xList)
    {
         // Internally appending all const char* present in xList and 
         // populating String class char buffer
    } 

};

知道如何實現這一目標嗎? 我的印象是,以下事情應該可以工作……但事實並非如此。

template <const char* ... Args>
String(Args... xList)
{
    
} 

可能有一種使用va_arg的方法,但我對此不感興趣。

實現您想要的方法是采用任意類型的 arguments ,然后使用SFINAE約束它們。 在 C++11/14 中,您需要一些額外的樣板代碼:

template<class...>
struct conjunction : std::true_type {};

template<class B>
struct conjunction<B> : B {};

template<class B, class... Bn>
struct conjunction<B, Bn...> 
    : std::conditional_t<B::value, conjunction<Bn...>, B> {};

class String
{
public: 
    template<class... Args, typename = std::enable_if_t<
        conjunction<std::is_convertible<Args, const char*>...>::value>>
    String(const Args&... list)
    {} 
};

在 C++17 中,解決方案更短:

class String
{
public: 
    template<class... Args, typename = std::enable_if_t<
        (std::is_convertible_v<Args, const char*> && ...)>>
    String(const Args&... list)
    {} 
};

這是一個使用可變參數模板和SFINAE的工作示例,如果您不提供const char* s,它將無法編譯

#include <type_traits>
#include <list>
#include <iostream>

struct String
{
    std::list<char> ls;
    template<class ... Args, class = std::enable_if_t<std::is_same_v<std::common_type_t<Args...>, const char *>>>
    String(Args...args):ls{*args...}
    {
    }

};

int main(){
    auto c1 = 'a'; const char * pc1 = &c1;
    auto c2 = 'b'; const char * pc2 = &c2;
    auto c3 = 'c'; const char * pc3 = &c3;
    String s{pc1, pc2, pc3};

    for(auto it = s.ls.begin();it != s.ls.end(); ++it)std::cout << *it;
}

居住

使用c++11 ,代碼可以是這樣的

#include <type_traits>
#include <list>
#include <iostream>

struct String
{
    std::list<char> ls;

    template<class ... Args, class = typename std::enable_if<std::is_same<typename std::common_type<Args...>::type, const char *>::value>::type>
    String(Args...args):ls{*args...}
    {
    }

};

int main(){
    auto c1 = 'a'; const char * pc1 = &c1;
    auto c2 = 'b'; const char * pc2 = &c2;
    auto c3 = 'c'; const char * pc3 = &c3;
    String s{pc1, pc2, pc3};

    for(auto it = s.ls.begin();it != s.ls.end(); ++it)std::cout << *it;
}

居住

不完全是你問的,但是......如果你接受額外的幾個括號調用構造函數,你可以傳遞你的char const *的可變參數列表,如下所示

struct foo
 {
   template <std::size_t Dim>
   foo (char const * const (&arr)[Dim])
    { /* do something with arr */ }
 };

缺點是不能如下調用

foo f("one", "two", "three");

但你必須添加括號

// ...V.....................V
foo f({"one", "two", "three"});

下面是一個完整的編譯示例

#include <iostream>

struct foo
 {
   template <std::size_t Dim>
   foo (char const * const (&arr)[Dim])
    {
      for ( auto const & str : arr )
         std::cout << str << std::endl;
    } 
};

int main ()
 { 
   foo f({"one", "two", "three"});
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM