供您参考,编译时失败通常会阻止编译......这就是它们毕竟在这里的原因。
我可以想到两种方法来做你提议的事情:
SFINAE
从字面上看,SFINAE的意思是:替换失败不是错误。它适用于模板上下文,并允许从重载集中悄悄地丢弃证明不足的函数。SFINAE 的使用引发了概念检查的概念以及使用用于支持这些检查的特征对属性进行分类。
在您的情况下,这意味着如果您可以以某种方式将要测试的表达式放在 SFINAE 可能适用的上下文中,那么您可以尝试检测特定函数已被有效丢弃。
例如:
#include <iostream>
#include <utility>
struct Foo {};
struct Bar {};
template <typename T>
auto foo(T t) -> decltype(std::declval<Foo>() + t) { std::cout << "T\n"; }
void foo(...) { std::cout << "ellipsis\n"; }
int main() { foo(Bar()); }
产量:
ellipsis
(见ideone)即使在operator+(Foo, Bar)
任何地方都没有定义。
不幸的是,这可能并非在所有情况下都有效(尚不确定),但它应该可以在所有兼容的编译器上移植。
编译器特定
另一种可能性是使用编译器特定的功能。编译器测试套件必须验证这些编译器是否正确诊断错误,并且在您的情况下,在static_assert
满足条件时确实会发出错误。因此,编译器可能对此有钩子。
例如,在 Clang 测试套件中可以找到一个SemaCXX/static-assert.cpp
文件:
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
int f();
static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}}
static_assert(true, "true is not false");
static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
void g() {
static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
}
class C {
static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
};
template<int N> struct T {
static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}}
};
T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}}
T<2> t2;
template<typename T> struct S {
static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}}
};
S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}}
S<int> s2;
-fsyntax-only
避免代码生成-verify
意味着编译器检查,expected-note
和expected-warning
指定expected-error
是否正确满足。
如果不是,则编译器将返回错误代码。当然,这可能是特定于编译器的。