You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
2.9 KiB
C++
136 lines
2.9 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
// Test the set of C++11 features that Clang provides as an extension in C++03 mode.
|
|
// The language features we expect are:
|
|
//
|
|
// 1. rvalue references (and perfect forwarding)
|
|
// 2. variadic templates
|
|
// 3. alias templates
|
|
// 4. defaulted and deleted functions.
|
|
// 5. default values for non-type template parameters.
|
|
//
|
|
// Some features we don't get and can't be used in extended C++03 mode:
|
|
//
|
|
// 1. noexcept and constexpr
|
|
// 2. Two closing '>' without a space.
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic ignored "-Wc++11-extensions"
|
|
#endif
|
|
|
|
#include <type_traits>
|
|
#include <cassert>
|
|
|
|
// Equals delete and default are allowed in minimal C++03 mode.
|
|
namespace test_eq_delete_and_default {
|
|
void t1() = delete;
|
|
struct T2 {
|
|
T2() = default;
|
|
T2(T2 const&) = delete;
|
|
};
|
|
}
|
|
|
|
namespace alias_templates {
|
|
template <class T>
|
|
using X = T;
|
|
static_assert((std::is_same<X<int>, int>::value), "");
|
|
}
|
|
|
|
namespace variadics_templates {
|
|
template <class ...Args>
|
|
int t1(Args...) {
|
|
return sizeof...(Args);
|
|
}
|
|
void test() {
|
|
assert(t1() == 0);
|
|
assert(t1(42) == 1);
|
|
assert(t1(1, 2, 3) == 3);
|
|
}
|
|
}
|
|
|
|
namespace rvalue_references_move_semantics {
|
|
struct T {
|
|
T() : moved(0) {}
|
|
T(T const& other) : moved(other.moved) {}
|
|
T(T&& other) : moved(other.moved) { ++moved; other.moved = -1; }
|
|
int moved;
|
|
};
|
|
void f(T o, int expect_moved) { assert(o.moved == expect_moved); }
|
|
void test() {
|
|
{
|
|
T t;
|
|
assert(t.moved == 0);
|
|
T t2(static_cast<T&&>(t));
|
|
assert(t2.moved == 1);
|
|
assert(t.moved == -1);
|
|
}
|
|
{
|
|
T t;
|
|
f(t, 0);
|
|
f(static_cast<T&&>(t), 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace rvalue_references_perfect_forwarding {
|
|
template <class Expect, class T>
|
|
void f(T&&) {
|
|
static_assert((std::is_same<Expect, T&&>::value), "");
|
|
}
|
|
void test() {
|
|
int x = 42;
|
|
f<int&>(x);
|
|
f<int&&>(42);
|
|
f<int&&>(static_cast<int&&>(x));
|
|
}
|
|
}
|
|
|
|
namespace default_values_for_nttp {
|
|
template <int I = 42>
|
|
void f() { assert(I == 42); }
|
|
void test() {
|
|
f();
|
|
}
|
|
}
|
|
|
|
namespace reference_qualified_functions {
|
|
struct T {
|
|
T() : lvalue_called(0), rvalue_called(0) {}
|
|
void foo() const & { lvalue_called++; }
|
|
void foo() && { rvalue_called++; }
|
|
mutable int lvalue_called;
|
|
int rvalue_called;
|
|
};
|
|
|
|
void test() {
|
|
{
|
|
T t;
|
|
t.foo();
|
|
assert(t.lvalue_called == 1);
|
|
assert(t.rvalue_called == 0);
|
|
}
|
|
{
|
|
T t;
|
|
static_cast<T&&>(t).foo();
|
|
assert(t.lvalue_called == 0);
|
|
assert(t.rvalue_called == 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int, char**) {
|
|
variadics_templates::test();
|
|
rvalue_references_move_semantics::test();
|
|
rvalue_references_perfect_forwarding::test();
|
|
default_values_for_nttp::test();
|
|
reference_qualified_functions::test();
|
|
return 0;
|
|
}
|