【发布时间】:2013-02-20 09:11:14
【问题描述】:
我正在升级一些 C++ 代码以利用 C++11 中的新功能。我有一个特征类,其中有几个函数返回基本类型,这些基本类型在大多数情况下(但并非总是)返回一个常量表达式。我想根据函数是否为constexpr 做不同的事情。我想出了以下方法:
template<typename Trait>
struct test
{
template<int Value = Trait::f()>
static std::true_type do_call(int){ return std::true_type(); }
static std::false_type do_call(...){ return std::false_type(); }
static bool call(){ return do_call(0); }
};
struct trait
{
static int f(){ return 15; }
};
struct ctrait
{
static constexpr int f(){ return 20; }
};
int main()
{
std::cout << "regular: " << test<trait>::call() << std::endl;
std::cout << "constexpr: " << test<ctrait>::call() << std::endl;
}
额外的int/... 参数在那里,如果在SFINAE 之后两个函数都可用,则通过重载分辨率选择第一个函数。
使用 Clang 3.2 编译和运行它显示:
regular: 0
constexpr: 1
所以这似乎可行,但我想知道代码是否合法 C++11。特别是因为我理解 SFINAE 的规则已经改变。
【问题讨论】:
-
有趣的问题。我写了一个我认为证明它是合法的答案,但后来我写了一个modified version,根据我的答案应该同样有效,而且它不能在任何编译器上编译。所以我不打算提交答案,但我很好奇。
-
@AndyProwl:我很好奇,您能否在 liveworkspace.org 或其他类似网站上发布您的解决方案?
-
@K-ballo:如果你的意思是答案,是的。我把它贴在这里并删除它,你仍然可以看到它。
-
@andy 我认为您的想法错误是假设扣除期间的替换将替换为默认模板参数。但如果你仔细观察,你会发现默认模板参数已经被更高一级的类模板所取代。当实例化类模板特化的成员声明时,成员模板的默认模板参数不会立即实例化,而只会在使用时实例化。然而,这并不意味着它们在使用点的实例化是一个 SFINAE 上下文。
标签: c++ templates c++11 sfinae constexpr