我想进入更多的模板元编程.我知道SFINAE代表"替换失败不是错误".但是有人能告诉我SFINAE的用处吗?
我必须在C中做这样的事情.它只有在我使用char时才有效,但我需要一个字符串.我怎样才能做到这一点?
#define USER "jack" // jack or queen
#if USER == "jack"
#define USER_VS "queen"
#elif USER == "queen"
#define USER_VS "jack"
#endif
Run Code Online (Sandbox Code Playgroud) 我在将一些东西从Solaris移植到Linux时遇到的一个问题是Solaris编译器__FILE__在预处理过程中将宏扩展为文件名(例如MyFile.cpp),而Linux上的gcc扩展到完整路径(例如/ home /用户/ MYFILE.CPP).使用basename()可以很容易地解决这个问题但是......如果你经常使用它,那么对basename()的所有调用都必须加起来,对吧?
这是问题所在.有没有办法使用模板和静态元编程,在编译时运行basename()或类似的?由于它__FILE__是常量且在编译时已知,因此可能更容易.你怎么看?可以吗?
作为免责声明,我在询问之前已对此进行过研究.我发现了一个类似的问题,但答案有点"稻草人",并没有真正回答我个人的问题.我也提到了我方便的cppreference页面,但这并没有提供对事物的非常"愚蠢"的解释.
基本上我还在继续constexpr,但目前我的理解是它需要在编译时评估表达式.由于它们可能仅在编译时存在,因此它们在运行时不会真正具有内存地址.因此,当我看到人们使用时static constexpr(例如在类中)static会让我感到困惑...... 因为这只对运行时上下文有用,所以在这里会是多余的.
我在" constexpr除了编译时表达式之外不允许任何东西"声明中看到了矛盾(特别是在SO).但是,Bjarne Stroustrup的页面中的一篇文章在各种示例中解释了实际上constexpr 确实需要在编译时对表达式进行评估.如果不是,则应生成编译器错误.
我之前的段落似乎有点偏离主题,但它是理解为什么static可以或应该使用的必要基线constexpr.不幸的是,该基线有很多矛盾的信息浮出水面.
任何人都可以帮助我将所有这些信息整合到纯粹的事实中,并提供有意义的示例和概念吗?基本上在了解constexpr真实行为的基础上,您为什么要使用static它?通过什么范围/场景确实static constexpr有意义,如果它们可以一起使用?
由于constexpr的扩展版本(我想从C++ 14开始),你可以声明constexpr函数,它们可以用作"真正的"constexpr,即代码在编译时执行或者可以表现为内联函数.那么什么时候可以有这个程序:
#include <iostream>
constexpr int foo(const int s) {
return s + 4;
}
int main()
{
std::cout << foo(3) << std::endl;
const int bar = 3;
std::cout << foo(bar) << std::endl;
constexpr int a = 3;
std::cout << foo(a) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,结果是:
7
7
7
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.所以我的问题是:如果函数在编译时或运行时执行,有没有办法(可能是标准的)知道foo(const int s)?
编辑:也可以在运行时知道在编译时是否评估了函数?
我想要一个编译时字符串加密,这样我就可以在我的代码中编写:
const auto encryptedInvalidLicense = ENCRYPT("Invalid license");
std::cout << encryptedInvalidLicense.decrypt() << std::endl; // outputs "Invalid license"
Run Code Online (Sandbox Code Playgroud)
并且字符串"Invalid license"不会出现在二进制文件中.预构建可能是答案,但我正在寻找一个纯c ++ constexpr解决方案来解决这个问题,它将得到VS2015的支持.
有什么建议?
我已经研究过编译时字符串加密,它没有为问题提供constexpr解决方案.
我还研究了http://www.unknowncheats.me/forum/c-and-c/113715-compile-time-string-encryption.html.虽然它是一个constexpr解决方案,但VS2015仍然将字符串纯文本添加到二进制文件中.
有没有办法constexpr在编译阶段和运行时实现函数的不同行为?
考虑以下示例(使用理论特征D: static if):
constexpr int pow( int base , int exp ) noexcept
{
static if( std::evaluated_during_translation() ) {
auto result = 1;
for( int i = 0 ; i < exp ; i++ )
result *= base;
return result;
} else { // std::evaluated_during_runtime()
return std::pow( base , exp );
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有,有没有办法限制constexpr只编译时间?
我想创建一个可以比较2个字符串的宏,如果不满足条件则发出编译时错误.这可能是编译时断言.
我不知道怎么能这样做.
例如:
STATIC_COMPARE("THIS STRING","THIS STRING") -> would emit a compile time error
STATIC_COMPARE("THIS STRING","THIS OTHER STRING) -> wouldn't emit a compile time error.
Run Code Online (Sandbox Code Playgroud)
宏会看起来像
#define STATIC_COMPARE(str1,str2) if (str1==str2) emit an error with a message
Run Code Online (Sandbox Code Playgroud)
所以我想问题归结为能够在编译时比较2个字符串.
在对另一个问题的评论中,用户hvd声明了以下内容:
...虽然字符串文字可以传递给
constexpr函数,并且在常量表达式中的字符串文字上允许数组索引,但constexpr函数参数的索引操作不符合常量表达式.
我并不完全明白这是什么意思.这是否意味着hash_value以下代码中的变量
#include <cstddef>
// Compute the hash of a string literal adding the values of its characters
template<std::size_t N> constexpr std::size_t
hash_string
( const char (& s)[N] )
noexcept
{
std::size_t h = 0;
// Array indexing happening under the hood
for ( const auto c : s )
h += c;
return h;
}
constexpr auto hash_value = hash_string("Hello, world!");
Run Code Online (Sandbox Code Playgroud)
无法在编译时进行评估?你能详细说明引用的评论并告诉我是否正确吗?
我以为我会尝试通过散列来选择不同的选项作为字符串,但这不起作用:
#include <type_traits>
#include <string>
inline void selectMenuOptionString(const std::string& str)
{
switch (std::hash<std::string>()(str))
{
case std::hash<std::string>()(std::string("Selection one")) : break;
// Expression must have a constant value
}
}
inline void selectMenuOptionString2(const std::string& str)
{
size_t selectionOneHash = std::hash<std::string>()(std::string("Selection one"));
switch (std::hash<std::string>()(str))
{
case selectionOneHash: // Expression must have a constant value
// The variable of selectionOneHash cannot be used as a constant
}
constexpr size_t hash = std::hash<int>()(6); // Expression must have a constant value
}
Run Code Online (Sandbox Code Playgroud)
似乎我无法在编译时获取哈希值.根据我的阅读,每次不同的输入应该每次产生相同的唯一输出,碰撞的可能性非常低.鉴于这些属性无法在编译时计算哈希值?我对哈希很不了解,我通常使用unordered_map,但我想尝试新的东西以便学习.
我找到了这段代码,并想知道我是否真的应该在我的真实项目中实现这样的东西.
令我困惑的事情是
这需要更多的编译时间,但我不应该以运行时为代价来打扰编译时间.
如果N真的是一个非常大的数字呢?源代码中是否有文件大小限制?
或者它的好事要知道,而不是实施?
#include <iostream>
using namespace std;
template<int N>
class Factorial {
public:
static const int value = N * Factorial<N-1>::value;
};
template <>
class Factorial<1> {
public:
static const int value = 1;
};
int main() {
Factorial<5L> f;
cout << "5! = " << f.value << endl;
}
Run Code Online (Sandbox Code Playgroud)
输出:
5! = 120
Run Code Online (Sandbox Code Playgroud)
稍微修改一下,因为我正在玩代码,发现了
Factorial<12> f1; // works
Factorial<13> f2; // doesn't work
Run Code Online (Sandbox Code Playgroud)
错误:
undefined reference to `Factorial<13>::value'
Run Code Online (Sandbox Code Playgroud)
是不是可以12进一步深入?
我正在创建一个带有一些硬编码参数的 C 程序。(这是设计使然,不用担心。)
//global constants
const char * const USERNAME = "username";
const int USERNAME_LEN = strlen(USERNAME);
Run Code Online (Sandbox Code Playgroud)
当然,这是错误的,因为 strlen 显然不是一个常量。有没有办法做到这一点?或者我应该不关心并直接从 strlen 传递 strncmp 结果?