2017-10-13 119 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