2017-10-13 106 views
1

結果我有constexpr函數計算佔位符https://godbolt.org/g/JcxSiu的數量,編譯時間檢查的sizeof ...(參數)與從constexpr功能

e.g: 「Hello %1」 返回1和 「Hello %1, time is %2」 返回2

然後,我想作出一個函數,如果參數的數量不等於佔位符的數量,它不會編譯。

template <typename... Args> 
inline std::string make(const char* text, Args&&... args) { 
    constexpr static unsigned count = sizeof...(args); 

    // TODO how to compile time check if count == count_placeholders(text)  
    // constexpr static auto np = count_placeholders(text); 

    //static_assert(count == np;, "Wrong number of arguments in make"); 

    return std::to_string(count); 
}; 

使 make("Hello %1", "World");編譯和

make("Hello %1 %2", "World");make("Hello %1", "World", "John");沒有。

我認爲這是可以做到的,我只是不知道如何。也許一些模板magick :)

編輯

我幾乎得到了我想要的東西。 https://godbolt.org/g/Y3q2f8

現在以調試模式中止。編譯時錯誤是可能的?

+0

這是**沒有答案**,因爲它使用GNU擴展buf,如果它不打擾你可以使用[字符串文字模板](https://wandbox.org/permlink/bSLW5DNEX4gNuDyw)。這將適用於gcc和clang,但可能不適用於任何其他編譯器...... –

+0

這可能不是一個可以接受的答案,但這裏是使用Boost.Metaparse宏的解決方案。 [實施例](https://godbolt.org/g/tZYzyH)。 – llonesmiz

回答

2

我的第一個想法是使用SFINAE啓用/禁用make();像

template <typename... Args> 
auto make(const char* text, Args&&... args) 
    -> std::enable_if_t<sizeof...(args) == count_placeholders(text), 
         std::string> 
{ 
    // ... 
} 

不幸的是這並沒有編譯,因爲text不能在constexpr使用。

但是,如果你接受text是一個模板參數(在編譯時間,所以知道),你可以做一些事情作爲

template <char const * const text, typename ... Args> 
auto makeS (Args && ... args) 
    -> std::enable_if_t<sizeof...(args) == count_plc(text), std::string> 
{ return std::to_string(sizeof...(args)); } 

下面是一個完整的工作示例

#include <string> 
#include <type_traits> 

constexpr std::size_t count_plc (char const * s, 
           std::size_t index = 0U, 
           std::size_t count = 0U) 
{ 
    if (s[index] == '\0') 
     return count; 
    else if ( (s[index] == '%') && (s[index+1U] != '\0') 
      && (s[index+1U] > '0') && (s[index+1U] <= '9')) 
     return count_plc(s, index + 1U, count+1U); 
    else 
     return count_plc(s, index + 1U, count); 
} 

template <char const * const text, typename ... Args> 
auto makeS (Args && ... args) 
    -> std::enable_if_t<sizeof...(args) == count_plc(text), std::string> 
{ return std::to_string(sizeof...(args)); } 

constexpr char const h1[] { "Hello %1" }; 
constexpr char const h2[] { "Hello %1 %2" }; 

int main() 
{ 
    makeS<h1>("World"); // compile 
    //makeS<h2>("World"); // compilation error 
    //makeS<h1>("World", "John"); // compilation error 
} 
+0

確實:constexpr函數的參數不能用作constexpr值。另外兩種可能性(如果你不想將自己限制爲一個'const char *'作爲非類型模板參數:(1)['make (text,「Hello」,「World」) ;'](https://godbolt.org/g/QfjRgf)或(2)(C++ 17?)['make([=] {return text;},「Hello」,「World」);'' ](https://godbolt.org/g/DHWbpM)。 – Julius