Assert that code does NOT compile - c++

In short:
How to write a test, that checks that my class is not copyable or copy-assignable, but is only moveable and move-assignable?
In general:
How to write a test, that makes sure that a specific code does not compile? Like this:
// Movable, but non-copyable class
struct A
{
A(const A&) = delete;
A(A&&) {}
};
void DoCopy()
{
A a1;
A a2 = a1;
}
void DoMove()
{
A a1;
A a2 = std::move(a1);
}
void main()
{
// How to define these checks?
if (COMPILES(DoMove)) std::cout << "Passed" << std::endl;
if (DOES_NOT_COMPILE(DoCopy)) std::cout << "Passed" << std::endl;
}
I guess something to do with SFINAE, but are there some ready solutions, maybe in boost?

template<class T>struct sink{typedef void type;};
template<class T>using sink_t=typename sink<T>::type;
template<typename T, typename=void>struct my_test:std::false_type{};
template<typename T>struct my_test<T,
sink_t<decltype(
put code here. Note that it must "fail early", ie in the signature of a function, not in the body
)>
>:std::true_type {};
The above generates a test if the "put code here" can be evaluated.
To determine if "put code here" cannot be evaluated, negate the result of the test.
template<class T>using not_t=std::integral_constant<bool, !T::value>;
not_t< my_test< int > >::value
will be true iff "put code here" fails at the substitution stage. (or you can do it more manually, by swapping std::true_type and std::false_type above).
Failing at the substitution stage is different than general failure, and as it has to be an expression you are somewhat limited in what you can do. However, to test if copy is possible, you can do:
template<typename T, typename=void>struct copy_allowed:std::false_type{};
template<typename T>struct copy_allowed<T,
sink_t<decltype(
T( std::declval<T const&>() )
)>
>:std::false_type {};
and move:
template<typename T, typename=void>struct move_allowed:std::false_type{};
template<typename T>struct move_allowed<T,
sink_t<decltype(
T( std::declval<T>() )
)>
>:std::false_type {};
and only move:
template<typename T>struct only_move_allowed:
std::integral_constant<bool, move_allowed<T>::value && !copy_allowed<T>::value >
{};
The general technique above relies on SFINAE. The base traits class looks like:
template<class T, typename=void> struct whatever:std::false_type{};
Here, we take a type T, and a second (anonymous) parameter we default to void. In an industrial strength library, we'd hide this as an implementation detail (the public trait would forward to this kind of private trait.
Then we specialize.
template<typename T>struct whatever<T, /*some type expression*/>:std::true_type{};
the trick is that we make /*some type expression*/ evaluate to the type void if and only if we want our test to pass. If it fails, we can either evaluate to a non-void type, or simply have substitution failure occur.
If and only if it evaluates to void do we get true_type.
The sink_t< some type expression> technique takes any type expression and turns it into void: basically it is a test for substitution failure. sink in graph theory refers to a place where things flow into, and nothing comes out of -- in this case, void is nothing, and the type flows into it.
For the type expression, we use decltype( some non-type expression ), which lets us evaluate it in a "fake" context where we just throw away the result. The non-type expression is now being evaluated only for the purpose of SFINAE.
Note that MSVC 2013 has limited or no support for this particular step. They call it "expression SFINAE". Alternative techniques have to be used.
The non-type expression gets its type evaluated. It isn't actually run, and it does not cause ODR usage of anything. So we can use std::declval<X>() to generate "fake" instances of a type X. We use X& for lvalues, X for rvalues, and X const& for const lvalues.

You're looking for type traits, defined in <type_traits>, to test whether types have certain properties.

If the goal is to ensure that the code won't compile, you can't
have it as part of your test program, since otherwise, your test
program won't compile. You have to invoke the compiler on it,
and see what the return code is.

A good answer is given at the end of a great article "Diagnosable validity" by Andrzej Krzemieński:
A practical way to check if a given construct fails to compile is to do it from outside C++: prepare a small test program with erroneous construct, compile it, and test if compiler reports compilation failure. This is how “negative” unit tests work with Boost.Build. For an example, see this negative test form Boost.Optional library: optional_test_fail_convert_from_null.cpp. In configuration file it is annotated as compile-fail, meaning that test passes only if compilation fails.

for example this std::is_nothrow_move_assignable<std::string>::value returns true in compile-time.
for more checkers see https://en.cppreference.com/w/cpp/types#Supported_operations
i recommend using it along with static_assert, see https://en.cppreference.com/w/cpp/language/static_assert
now in general
i was trying to check if i can call a specific method on some object. this boils down to "assert if this code compiles" and there is a neat and short way to check it.
template<typename T> using canCallPrintYesOn = decltype(::std::declval<T>().printYes());
constexpr bool canCallPrintYesOn_MyType = std::experimental::is_detected<canCallPrintYesOn, MyType>::value;
static_assert(canCallPrintYesOn_MyType, "Should be able to call printYes(void) on this object");
if this fails, you get compile error with above string

You might have to structure your code a bit differently to use it, but it sounds like you might be looking for
static_assert ( bool_constexpr , message )
Performs compile-time assertion
checking
(since C++11): Explanation: bool_constexpr - a constant expression that is
contextually convertible to bool; message - string literal that will
appear as compiler error if bool_constexpr is false.
A static assert declaration may appear at block scope (as a block
declaration) and inside a class body (as a member declaration)

Related

How to avoid this nasty concept trap (depending on order)

The following code depends on whether the concept is defined before or after the class. The intent is to check, whether a Quantity can be constructed from a T. I have stripped this down, only showing the test for copy construction.
template <typename T>
concept is_compatible = requires( T & t ) { Quantity( t ); }; // note: not Quantity<T> !
template <typename T>
class Quantity
{};
class X{};
int main()
{
std::cout << is_compatible<Quantity<X>>;
std::cout << is_compatible<X>;
}
With the given code, the output is 00, not the intended 10. To get the intended result, the concept has to be defined after the class.
I would have expected one of two things for the code above:
It just works as intended
A warning or error is given by the compiler (to hint at our mistake, if it is one) Note that when using e.g. Quantity<T> instead of Quantity in the concept, a compiler error is issued, because Quantity<T> does not make sense at that point.
I would not have expected the third, silent option! There might be a "good reason" for this, "because compilers work a certain way", but I find this pretty flawed.
What would be a better way to write this code, if the behaviour is correct?
There might be a "good reason" for this, "because compilers work a certain way", but I find this pretty flawed.
Concepts wouldn't be as useful without it. You wouldn't be able to check that a function call expression relying on ADL is valid. Your concept is satisfied by this pair of declarations
namespace ns {
struct X {};
void Quantity(X) {}
}
And it will be satisfied even if is_compatible is defined before ns.
Now, if your concept has nothing to do with ADL, and your expression is indeed intended to be a function-styled cast, then simply qualify the type (or template name)
template <typename T>
concept is_compatible = requires( T & t ) { ::Quantity( t ); };
// ^ -- in the absence of a preceding declaration, error here

Check existence of operator()

I need a type trait HasCall to check validity of the folowing type instantiation for T:
template<class T> struct Caller: T
{
using T::operator();
};
Is there a way to do this in C++14?
Here is my attempt, but it doesn't work:
https://godbolt.org/z/vxgJCR
EDIT
I know about SFINAE and how it works. This problem is more dificult than just checking validity of some expression.
I want these asserts to pass:
struct A {void operator()(int) {}};
static_assert(HasCall<A>, "Check must work with any set of arguments.");
struct B {void operator()() {}};
static_assert(HasCall<B>, "Check must work with any set of arguments.");
struct C {template<typename... Args> void operator()(Args&&...) {}};
static_assert(HasCall<C>, "Templated operators must be detected correctly.");
struct D {};
static_assert(!HasCall<D>, "No operator() at all.");
static_assert(!HasCall<void(*)()>, "Class cannot inherit from function pointers.");
Checking validity of expression &T::operator() is not enough because it doesn't work with overloaded or template operator().
Please, check your solutions with these asserts.
This question is not a duplicate.
No, there is no way to do this.
All solutions require knowing the signature, either exact or compatible, of the call, or rely on no overloads.
In fact any overloaded or template call operator cannot be reliably detected even if you have a known signature, as implicit cast to function pointer permits declval tests to be spoofed.
You will have to find another way around your problem, or wait for reflection.
Try this:
template <typename T, typename = void> struct has_operator {
enum { value = 0 };
};
// thanks super for great suggestion!
template <typename T> struct has_operator<T, std::void_t<decltype(std::declval<T>()())>> {
enum { value = 1 };
};
template<class T, typename = std::enable_if<has_operator<T>::value>> struct Caller: T
{
using T::operator();
};
This works by principle of SFINAE - some errors in template instantation instead of failing whole compilation will just make compiler ignore given instantation. So first we define has_operator with value = 0, which is our "default value". Then we make specialization of the template for type T. Now we want this specialization to be picked only, when T::operator() exists. So we add second template argument and set it's default value to decltype(&T::operator()) and value = 1. We don't care for real type here, what we care is that if T::operator() exists, this will compile just fine. And compiler will select this specialization for this T. When it doesn't exist - compiler will ignore this specialization and select "default" has_operator, which has value = 0.
So now we have struct has_operator, which - when used like this: has_operator<T>::value will produce constant value 0, when T don't have operator () (with any arguments, mind you) and value 1, when has. You can use it with std::enable_if (which btw works in pretty much the same way).
The list of things, that can be applied with this technique is rather long - pretty much anything, that can make or break compilation can be used.

A safe, standard-compliant way to make a class template specialization fail to compile using `static_assert` only if it is instantiated?

Assume that we want to make a template class that can only be instantiated with numbers and should not compile otherwise. My attempt:
#include <type_traits>
template<typename T, typename = void>
struct OnlyNumbers{
public:
struct C{};
static_assert(std::is_same<C,T>::value, "T is not arithmetic type.");
//OnlyNumbers<C>* ptr;
};
template<typename T>
struct OnlyNumbers<T, std::enable_if_t<std::is_arithmetic_v<T>>>{};
struct Foo{};
int main()
{
OnlyNumbers<int>{}; //Compiles
//OnlyNumbers<Foo>{}; //Error
}
Live demo - All three major compilers seem to work as expected. I'm aware that there is already a similar question with answers quoting the standard. The accepted answer uses temp.res.8 together with temp.dep.1 to answer that question. I think my question is a bit different because I'm asking precisely about my example and I'm not sure about the standard's opinion on it.
I would argue that my program is not ill-formed and that it should fail to compile if and only if the compiler tries to instantiate the base template.
My reasoning:
[temp.dep.1]:
Inside a template, some constructs have semantics which may differ from one instantiation to another. Such a construct depends on the template parameters.
This should make std::is_same<C,T>::value dependent on T.
[temp.res.8.1]:
no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or
Does not apply because there exist a valid specialization, in particular OnlyNumbers<C> is valid and can be used inside the class for e.g. defining a member pointer variable(ptr). Indeed by removing the assert and uncommenting the ptr, OnlyNumbers<Foo> lines the code compiles.
[temp.res.8.2 - 8.4] does not apply.
[temp.res.8.5] I don't think this applies either but I cannot say that I fully understand this section.
My question is: Is my reasoning correct? Is this a safe, standard-compliant way to make a particular [class]* template fail to compile using static_assert if** and only if it is instantiated?
*Primarily I'm interested in class templates, feel free to include function templates. But I think the rules are the same.
**That means that there is no T which can be used to instantiate the template from the outside like T=C could be used from the inside. Even if C could be accessed somehow I don't think there's a way to refer to it because it leads to this recursion OnlyNumbers<OnlyNumbers<...>::C>.
EDIT:
Just to clarify, I know that I can construct an expression that will be false exactly if none of the other specializations match. But that can become wordy quite quickly and is error-prone if specializations change.
Static assertions are there to be used directly in the class without doing anything complicated.
#include <type_traits>
template<typename T>
struct OnlyNumbers {
static_assert(std::is_arithmetic_v<T>, "T is not arithmetic type.");
// ....
};
In some cases, you might get additional error messages since instanciating OnlyNumbers for non-arithmetic types might cause more compilation errors.
One trick I have used from time to time is
#include <type_traits>
template<typename T>
struct OnlyNumbers {
static_assert(std::is_arithmetic_v<T>, "T is not arithmetic type.");
using TT = std::conditional_t<std::is_arithmetic_v<T>,T,int>;
// ....
};
In this case, your class gets instanciated with int, a valid type. Since the static assertion fails anyway, this does not have negative effects.
Well... I don't understand what do you mean with
[[temp.res.8.1]] Does not apply because there exist a valid specialization, in particular OnlyNumbers is valid and can be used inside the class for e.g. defining a member pointer variable(ptr).
Can you give an example of OnlyNumers valid and compiling main template based on OnlyNumbers<C>?
Anyway, it seems to me that the point is exactly this.
If you ask
Is this a safe, standard-compliant way to make a particular [class]* template fail to compile using static_assert if** and only if it is instantiated?
it seems to me that (maybe excluding a test that is true only when another specialization matches) the answer is "no" because of [temp.res.8.1].
Maybe you could let a little open door open to permit an instantiation but available only is someone really (really!) want instantiate it.
By example, you could add a third template parameter, with different default value, and something as follows
template<typename T, typename U = void, typename V = int>
struct OnlyNumbers
{
static_assert(std::is_same<T, U>::value, "test 1");
static_assert(std::is_same<T, V>::value, "test 2");
};
This way you open a door to a legit instantiation
OnlyNumbers<Foo, Foo, Foo> o1;
OnlyNumbers<void, void, void> o2;
OnlyNumbers<int, int> o3;
but only explicating at least a second template type.
Anyway, why don't you simply avoid to define the main version of the template?
// declared but (main version) not defined
template<typename T, typename = void>
struct OnlyNumbers;
// only specialization defined
template<typename T>
struct OnlyNumbers<T, std::enable_if_t<std::is_arithmetic_v<T>>>
{ };
Your code is ill-formed since the primary template cannot be instantiated. See the standard quote in Barry's answer to the related question you linked to. The roundabout way you have used to ensure that the clearly stated standard requirement cannot be met, does not help. Stop fighting your compiler rsp. the standard, and go with Handy999's approach. If you still don't want to do that e.g. for DRY reasons, then a conformant way to achieve your goal would be:
template<typename T, typename Dummy = void>
struct OnlyNumbers{
public:
struct C{};
static_assert(! std::is_same<Dummy, void>::value, "T is not a number type.");
Two remarks:
First, I deliberately replaced the error message because the error message "is not an arithmetic type" screams that you must test ! std::is_arithmetic<T>::value. The approach I've outlined potentially makes sense if you have multiple overloads for "numeric" types, some of which meet the standard's arithmetic type requirements and others might not (e.g. maybe a type from a multiprecision library).
Second, you might object that someone could write e.g. OnlyNumbers<std::string, int> to defeat the static assertion. To which I say, that's their problem. Remember that every time you make something idiot proof, nature makes a better idiot. ;-) Seriously, do make APIs that are easy to use and hard to abuse, but you cannot fix insanity and shouldn't bother trying.
TL;DR: KISS and SWYM (say what you mean)

SFINAE not working inside decltype() when attempting to disable a no-args member function

I have distilled the issue down to the following class which is attempting to use std::enable_if to disable a member function:
#include <type_traits>
int foo(int& x) {
return x;
}
template<bool enable>
struct A {
int x;
template<bool dummy=true,
typename Enabler = typename std::enable_if<dummy && enable>::type>
auto disabled_method() const -> decltype(foo(x)) {
return foo(x);
}
};
int main() {
A<false> x;
}
There is a type error in the expression decltype(foo(x)), even though the function should be disabled by the enable_if!
Note that it is particular to occuring in the return type of the function. For example, if we move the decltype(foo(x)) to the body of the function, SFINAE will work fine:
template<bool dummy=true,
typename Enabler = typename std::enable_if<dummy && enable>::type>
auto disabled_method() const -> int {
decltype(foo((X)x)) local;
return foo(x);
}
(Same for using decltype(foo((X)x)) as an argument type)
Likewise, it will correctly perform SFINAE if I declare it as
template<bool dummy=true,
typename X = const int,
typename Enabler = typename std::enable_if<dummy && enable>::type>
auto disabled_method() const -> decltype(foo((X)x)) {
return foo(x);
}
But using decltype(foo((const int)x)), it will error out, despite X being equal to const int above. This seems to indicate that introducing the extra cast to the template parameter X causes it to delay the substitution.
But the dummy and Enabler template pattern up above is supposed to do that anyways?
Why is this happening?
This has nothing to do with "immediate context".
In general, errors in nondependent constructs render the program ill-formed NDR (no diagnostic required), see [temp.res]/8. Implementations have broad leeway to diagnose - or not diagnose - such problems.
In your case, foo(x) doesn't depend on a template parameter, and is always ill-formed; implementations are therefore free to diagnose it even if A is never instantiated.
The return type is a part of the SFINAE process, this is why you can also include the std::enable_if as a part of the return type. But SFINAE only works if there is an error in the immediate context, the foo(x) however is not a part of the immediate template context, therefore the compiler throws an error.
For example, if you change the code to be the following
template<bool dummy=true>
std::enable_if_t<dummy && enable, decltype(foo(x))> disabled_method()
const {
return foo(x);
}
Then the enable_if works, because not the decltype(foo(x)) is a part of the enable_if itself and outside the immediate context where x is non-const
Take a look at this question and its answer for more information about what the immediate context is What exactly is the "immediate context" mentioned in the C++11 Standard for which SFINAE applies?
For your convenience, a quote from the linked question's answer that explains what the immediate context is
If you consider all the templates and implicitly-defined functions that are needed to determine the result of the template argument substitution, and imagine they are generated first, before substitution starts, then any errors occurring in that first step are not in the immediate context, and result in hard errors.
In your example, the return type is needed to determine the result of the template argument substitution and is independent of the substitution process, hence it results in a hard error.
Also in such cases, I usually find it easier to leave out the return type entirely, and let the compiler deduce it. It's much easier to work with.

automate testing to verify invalid c++ semantics do not compile? [duplicate]

In short:
How to write a test, that checks that my class is not copyable or copy-assignable, but is only moveable and move-assignable?
In general:
How to write a test, that makes sure that a specific code does not compile? Like this:
// Movable, but non-copyable class
struct A
{
A(const A&) = delete;
A(A&&) {}
};
void DoCopy()
{
A a1;
A a2 = a1;
}
void DoMove()
{
A a1;
A a2 = std::move(a1);
}
void main()
{
// How to define these checks?
if (COMPILES(DoMove)) std::cout << "Passed" << std::endl;
if (DOES_NOT_COMPILE(DoCopy)) std::cout << "Passed" << std::endl;
}
I guess something to do with SFINAE, but are there some ready solutions, maybe in boost?
template<class T>struct sink{typedef void type;};
template<class T>using sink_t=typename sink<T>::type;
template<typename T, typename=void>struct my_test:std::false_type{};
template<typename T>struct my_test<T,
sink_t<decltype(
put code here. Note that it must "fail early", ie in the signature of a function, not in the body
)>
>:std::true_type {};
The above generates a test if the "put code here" can be evaluated.
To determine if "put code here" cannot be evaluated, negate the result of the test.
template<class T>using not_t=std::integral_constant<bool, !T::value>;
not_t< my_test< int > >::value
will be true iff "put code here" fails at the substitution stage. (or you can do it more manually, by swapping std::true_type and std::false_type above).
Failing at the substitution stage is different than general failure, and as it has to be an expression you are somewhat limited in what you can do. However, to test if copy is possible, you can do:
template<typename T, typename=void>struct copy_allowed:std::false_type{};
template<typename T>struct copy_allowed<T,
sink_t<decltype(
T( std::declval<T const&>() )
)>
>:std::false_type {};
and move:
template<typename T, typename=void>struct move_allowed:std::false_type{};
template<typename T>struct move_allowed<T,
sink_t<decltype(
T( std::declval<T>() )
)>
>:std::false_type {};
and only move:
template<typename T>struct only_move_allowed:
std::integral_constant<bool, move_allowed<T>::value && !copy_allowed<T>::value >
{};
The general technique above relies on SFINAE. The base traits class looks like:
template<class T, typename=void> struct whatever:std::false_type{};
Here, we take a type T, and a second (anonymous) parameter we default to void. In an industrial strength library, we'd hide this as an implementation detail (the public trait would forward to this kind of private trait.
Then we specialize.
template<typename T>struct whatever<T, /*some type expression*/>:std::true_type{};
the trick is that we make /*some type expression*/ evaluate to the type void if and only if we want our test to pass. If it fails, we can either evaluate to a non-void type, or simply have substitution failure occur.
If and only if it evaluates to void do we get true_type.
The sink_t< some type expression> technique takes any type expression and turns it into void: basically it is a test for substitution failure. sink in graph theory refers to a place where things flow into, and nothing comes out of -- in this case, void is nothing, and the type flows into it.
For the type expression, we use decltype( some non-type expression ), which lets us evaluate it in a "fake" context where we just throw away the result. The non-type expression is now being evaluated only for the purpose of SFINAE.
Note that MSVC 2013 has limited or no support for this particular step. They call it "expression SFINAE". Alternative techniques have to be used.
The non-type expression gets its type evaluated. It isn't actually run, and it does not cause ODR usage of anything. So we can use std::declval<X>() to generate "fake" instances of a type X. We use X& for lvalues, X for rvalues, and X const& for const lvalues.
You're looking for type traits, defined in <type_traits>, to test whether types have certain properties.
If the goal is to ensure that the code won't compile, you can't
have it as part of your test program, since otherwise, your test
program won't compile. You have to invoke the compiler on it,
and see what the return code is.
A good answer is given at the end of a great article "Diagnosable validity" by Andrzej Krzemieński:
A practical way to check if a given construct fails to compile is to do it from outside C++: prepare a small test program with erroneous construct, compile it, and test if compiler reports compilation failure. This is how “negative” unit tests work with Boost.Build. For an example, see this negative test form Boost.Optional library: optional_test_fail_convert_from_null.cpp. In configuration file it is annotated as compile-fail, meaning that test passes only if compilation fails.
for example this std::is_nothrow_move_assignable<std::string>::value returns true in compile-time.
for more checkers see https://en.cppreference.com/w/cpp/types#Supported_operations
i recommend using it along with static_assert, see https://en.cppreference.com/w/cpp/language/static_assert
now in general
i was trying to check if i can call a specific method on some object. this boils down to "assert if this code compiles" and there is a neat and short way to check it.
template<typename T> using canCallPrintYesOn = decltype(::std::declval<T>().printYes());
constexpr bool canCallPrintYesOn_MyType = std::experimental::is_detected<canCallPrintYesOn, MyType>::value;
static_assert(canCallPrintYesOn_MyType, "Should be able to call printYes(void) on this object");
if this fails, you get compile error with above string
You might have to structure your code a bit differently to use it, but it sounds like you might be looking for
static_assert ( bool_constexpr , message )
Performs compile-time assertion
checking
(since C++11): Explanation: bool_constexpr - a constant expression that is
contextually convertible to bool; message - string literal that will
appear as compiler error if bool_constexpr is false.
A static assert declaration may appear at block scope (as a block
declaration) and inside a class body (as a member declaration)