Predicate Inheritance compilation error when using inline instantiation - c++

I'm using a test framework (tut) and noticed a lot of repeatability so I started to abstract out the predicate functions i needed. Below is a simplified example.
It works but I was hoping I could all do it in one line. The problem is when i try to instantiate the derived predicate class inline it fails to compile. Any ideas why?
#include <string>
#include <functional>
#include <iostream>
using namespace std;
template <class T>
struct TestPredicate : public binary_function<T,T,bool>
{
virtual bool operator() (const T& expected, const T& data) const = 0;
};
template <class T>
struct IsEqual : public TestPredicate<T>
{
virtual bool operator() (const T& expected, const T& data) const
{
cout << "IsEqual: " << expected << ", " << data << endl;
return data == expected;
}
};
template <class T>
struct IsNotEqual : public TestPredicate<T>
{
virtual bool operator() (const T& expected, const T& data) const
{
cout << "IsNotEqual: " << expected << ", " << data << endl;
return data != expected;
}
};
struct Tester
{
template <class T>
void test( const T& data, const T& expected, TestPredicate<T>& value_condition )
{
if ( value_condition( expected, data ) )
{
cout << "PASSED" << endl;
}
else
{
cout << "FAILED" << endl;
}
}
};
int main()
{
Tester test;
string data("hello");
string expected("hello");
// this doesn't compile with an inline instantiation of IsEqual
//test.test( data, expected, IsEqual<string>() ); // compilation error (see below)
// this works with an explicit instantiation of IsEqual
IsEqual<string> pred;
test.test( data, expected, pred );
return 0;
}
Compilation Output:
test2.cpp: In function ‘int main()’:
test2.cpp:61:48: error: no matching function for call to ‘Tester::test(std::string&, std::string&, IsEqual<std::basic_string<char> >)’
test2.cpp:61:48: note: candidate is:
test2.cpp:40:8: note: void Tester::test(const T&, const T&, TestPredicate<T>&) [with T = std::basic_string<char>]
test2.cpp:40:8: note: no known conversion for argument 3 from ‘IsEqual<std::basic_string<char> >’ to ‘TestPredicate<std::basic_string<char> >&’
Using g++ 4.6.3

In addition to the other answers, you don't really need runtime polymorphism with virtual functions. You could just make the tester take another template parameter:
template<class T, class Pred>
void test( const T& data, const T& expected, Pred value_condition )

Your Tester::test method needs to take a const reference to the predicate to work with both instantiations.

Temporary object are always const, that is way in test.test( data, expected, IsEqual<string>() ); IsEqual<string>() is of type const TestPredicate<T>.

The explanation to why the compiler complains is both simple and... a bit disheartening.
The C++ Standard rules out that a temporary object (such as created by the expression IsEqual<string>()) can be bound to a const reference, in which case its lifetime is extended to that of the reference.
Because Stroustrup feared that binding to non-const references would only be a source of bugs, it is not however allowed. With hindsight, it turns out that the absence of symmetry is often more surprising; VC++ allows binding to non-const references (as an extension). In C++11, the balance is somewhat restored by allowing binding to "reference reference" (&&), though it still leaves a gap...
... and leaves us in the unpleasant situation you find yourself in.
On the web this is may be referred to as the Most important const.

Related

Is there a way to get the type of a dereferenced value from a dereference-able type?

I'm playing around with C++ concepts and came across an interesting problem. I have the following two custom-defined concepts:
template<typename T>
concept is_dereferencable = requires (T t) { *t; };
template<typename T>
concept is_printable = requires (T t) { std::cout << t; };
As the names suggest, the first one is used to determine if a given type can be dereferenced, while the other one to check if a type supports output operator. I also have a function template called println, which looks like this:
template<typename T>
void println(const T& t)
{
if constexpr (is_dereferencable<T>) {
if constexpr (is_printable<decltype(*t)>) {
std::cout << *t << '\n';
}
} else if constexpr (is_printable<T>) {
std::cout << t << '\n';
}
}
This prints the dereferenced value *t if and only if type T is dereference-able and the type of the dereferenced value is printable. So, for example, I can use this function template with something like an std::optional:
int main
{
std::optional<std::string> stringOpt {"My Optional String"};
::println(stringOpt);
return 0;
}
This will print My Optional String as expected. While this is nice, the function will just silently print nothing if the type of a dereferenced value of a derefernce-able is not printable. So, for a user-defined type Person, the following will just print nothing:
struct Person
{
std::string m_name;
explicit Person(const std::string& name) : m_name {name} {}
};
int main
{
std::optional<Person> personOpt {"John Doe"}
::println(personOpt);
return 0;
}
So I would like to move the above compile-time ifs to a requires clause itself in order to get compile time errors in such cases. Is there a way to achieve that? Is there a way to get the dereferenced type of a given template type T? To make it a bit clearer, I would like to have something like this:
template<typename T>
requires is_dereferencable<T> && is_printable<decltype(*T)>
void printDereferencable(const T& t)
{
std::cout << *t << '\n';
}
P.S.: I understand that I could remove the nested if and just fail upon trying to call an output operator on something that doesn't support it. However, I want to specifically move this compile-time error to the concept to get a clearer error message.
another option is put the constraint after parameters, so it has access to them.
template<typename T>
void printDereferencable(const T& t)
requires is_dereferencable<const T&> && is_printable<decltype(*t)>
{
std::cout << *t << '\n';
}
note: it should test on const T&, not T
you can use std::declval
template<typename T>
requires is_dereferencable<const T&> && is_printable<decltype(*std::declval<const T&>())>
void printDereferencable(const T& t)
{
std::cout << *t << '\n';
}
or you can just write a is_dereference_printable concept
template<typename T>
concept is_dereference_printable = requires (T t) { std::cout << *t; };

Template deduction from std::bitset::operator[]

How does this code not compile? Why can bs[1] not be deduced to bool?
Is there a generic way to solve this problem?
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
template<typename T> struct StringConverter{};
template<> struct StringConverter<bool>{
std::string operator()(const bool &i){ return i?"true":"false"; }
};
template<typename T> std::string to_string(const T &val){
return StringConverter<T>()(val);
}
int main(){
// this does not compile
std::bitset<10> bs;
std::cout << to_string(bs[0]) << std::endl;
// this does
const std::bitset<10> bs_const;
std::cout << to_string(bs_const[0]) << std::endl;
}
Compiler Error:
main.cpp:12:12: error: type 'StringConverter<std::bitset<10>::reference>' does not provide a call operator
return StringConverter<T>()(val);
^~~~~~~~~~~~~~~~~~~~
main.cpp:18:18: note: in instantiation of function template specialization 'to_string<std::bitset<10>::reference>' requested here
std::cout << to_string(bs[0]) << std::endl;
^
1 error generated.
the non-const bitset::operator[] returns a proxy object rather than a bool (this has to be done because that proxy can be used to change the bit value). const bitset::operator[] however just returns a bool (not a reference, just a plain bool) so it matches for the StringConverter[
If you check the declaration of operator[], you'll notice it has two overloads - the const one, which returns bool and is used in your second example, and the non-const, which returns the object of type std::bitset::reference.
The latter is used for bit field modification, and it absolutely cannot be a bool& since it has to address a specific bit. The problem you ran into is quite common for these proxy return types (this is where I should mention vector<bool>).
As a possible solution you can use the fact that std::bitset::reference is convertible to bool (and is not convertible to any other conceivable type that you might use for your StringConverter specializations).

Why doesn't overloaded function bind to more specific overload?

Consider the following overloaded functions:
template <class T>
void foo(const T& v)
{
std::cout << "Generic version" << std::endl;
}
void foo(std::pair<const void*, std::size_t> p)
{
std::cout << "Pair version" << std::endl;
}
Below, I expect the second overload (the one that takes an std::pair) to be called:
int main()
{
const void* buf = 0;
std::size_t sz = 0;
foo(std::make_pair(buf, sz));
}
However, this code in fact calls the generic version. Why doesn't it bind to the overload that specifically takes an std::pair? Is this a compiler bug? I'm using a pretty old compiler, GCC 4.1.2
You need to declare your specialized function as a template
Your specialized argument type must follow the template parameter (i.e. be a const reference) as well.
Try
template <>
void foo(const std::pair<const void*, std::size_t>& p)
{
...
}

How do I avoid implicit conversions on non-constructing functions?

How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?
The following program compiles, although I'd like it not to:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
*please be sure to point out any misuse of terminology and assumptions
Define function template which matches all other types:
void function(int); // this will be selected for int only
template <class T>
void function(T) = delete; // C++11
This is because non-template functions with direct matching are always considered first. Then the function template with direct match are considered - so never function<int> will be used. But for anything else, like char, function<char> will be used - and this gives your compilation errrors:
void function(int) {}
template <class T>
void function(T) = delete; // C++11
int main() {
function(1);
function(char(1)); // line 12
}
ERRORS:
prog.cpp: In function 'int main()':
prog.cpp:4:6: error: deleted function 'void function(T) [with T = char]'
prog.cpp:12:20: error: used here
This is C++03 way:
// because this ugly code will give you compilation error for all other types
class DeleteOverload
{
private:
DeleteOverload(void*);
};
template <class T>
void function(T a, DeleteOverload = 0);
void function(int a)
{}
You can't directly, because a char automatically gets promoted to int.
You can resort to a trick though: create a function that takes a char as parameter and don't implement it. It will compile, but you'll get a linker error:
void function(int i)
{
}
void function(char i);
//or, in C++11
void function(char i) = delete;
Calling the function with a char parameter will break the build.
See http://ideone.com/2SRdM
Terminology: non-construcing functions? Do you mean a function that is not a constructor?
8 years later (PRE-C++20, see edit):
The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.
Namely:
// Where we want to only take int
template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
void func(T x) {
}
EDIT (c++20)
I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.
template <class T>
requires std::same_as(T,int)
void func(T x) {
//...
}
Small Edit (different pattern for concepts)
The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:
template <class T>
concept explicit_int = std::same_as<T,int>;
template <explicit_int T>
void func(T x) {
}
Small edit 2 (the last I promise)
Also a way to accomplish this possibility:
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
}
Here's a general solution that causes an error at compile time if function is called with anything but an int
template <typename T>
struct is_int { static const bool value = false; };
template <>
struct is_int<int> { static const bool value = true; };
template <typename T>
void function(T i) {
static_assert(is_int<T>::value, "argument is not int");
return;
}
int main() {
int i = 5;
char c = 'a';
function(i);
//function(c);
return 0;
}
It works by allowing any type for the argument to function but using is_int as a type-level predicate. The generic implementation of is_int has a false value but the explicit specialization for the int type has value true so that the static assert guarantees that the argument has exactly type int otherwise there is a compile error.
Maybe you can use a struct to make the second function private:
#include <cstdlib>
struct NoCast {
static void function(int i);
private:
static void function(char c);
};
int main(){
int i(5);
NoCast::function(i); //<- this is acceptable
char c('a');
NoCast::function(c); //<- Error
return EXIT_SUCCESS;
}
void NoCast::function(int i){return;}
This won't compile:
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: ‘static void NoCast::function(char)’ is private
prog.cpp:16: error: within this context
For C++14 (and I believe C++11), you can disable copy constructors by overloading rvalue-references as well:
Example:
Say you have a base Binding<C> class, where C is either the base Constraint class, or an inherited class. Say you are storing Binding<C> by value in a vector, and you pass a reference to the binding and you wish to ensure that you do not cause an implicit copy.
You may do so by deleting func(Binding<C>&& x) (per PiotrNycz's example) for rvalue-reference specific cases.
Snippet:
template<typename T>
void overload_info(const T& x) {
cout << "overload: " << "const " << name_trait<T>::name() << "&" << endl;
}
template<typename T>
void overload_info(T&& x) {
cout << "overload: " << name_trait<T>::name() << "&&" << endl;
}
template<typename T>
void disable_implicit_copy(T&& x) = delete;
template<typename T>
void disable_implicit_copy(const T& x) {
cout << "[valid] ";
overload_info<T>(x);
}
...
int main() {
Constraint c;
LinearConstraint lc(1);
Binding<Constraint> bc(&c, {});
Binding<LinearConstraint> blc(&lc, {});
CALL(overload_info<Binding<Constraint>>(bc));
CALL(overload_info<Binding<LinearConstraint>>(blc));
CALL(overload_info<Binding<Constraint>>(blc));
CALL(disable_implicit_copy<Binding<Constraint>>(bc));
// // Causes desired error
// CALL(disable_implicit_copy<Binding<Constraint>>(blc));
}
Output:
>>> overload_info(bc)
overload: T&&
>>> overload_info<Binding<Constraint>>(bc)
overload: const Binding<Constraint>&
>>> overload_info<Binding<LinearConstraint>>(blc)
overload: const Binding<LinearConstraint>&
>>> overload_info<Binding<Constraint>>(blc)
implicit copy: Binding<LinearConstraint> -> Binding<Constraint>
overload: Binding<Constraint>&&
>>> disable_implicit_copy<Binding<Constraint>>(bc)
[valid] overload: const Binding<Constraint>&
Error (with clang-3.9 in bazel, when offending line is uncommented):
cpp_quick/prevent_implicit_conversion.cc:116:8: error: call to deleted function 'disable_implicit_copy'
CALL(disable_implicit_copy<Binding<Constraint>>(blc));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full Source Code: prevent_implicit_conversion.cc
Well, I was going to answer this with the code below, but even though it works with Visual C++, in the sense of producing the desired compilation error, MinGW g++ 4.7.1 accepts it, and invokes the rvalue reference constructor!
I think it must be a compiler bug, but I could be wrong, so – anyone?
Anyway, here's the code, which may turn out to be a standard-compliant solution (or, it may turn out that that's a thinko on my part!):
#include <iostream>
#include <utility> // std::is_same, std::enable_if
using namespace std;
template< class Type >
struct Boxed
{
Type value;
template< class Arg >
Boxed(
Arg const& v,
typename enable_if< is_same< Type, Arg >::value, Arg >::type* = 0
)
: value( v )
{
wcout << "Generic!" << endl;
}
Boxed( Type&& v ): value( move( v ) )
{
wcout << "Rvalue!" << endl;
}
};
void function( Boxed< int > v ) {}
int main()
{
int i = 5;
function( i ); //<- this is acceptable
char c = 'a';
function( c ); //<- I would NOT like this to compile
}
I first tried PiotrNycz's approach (for C++03, which I'm forced to use for a project), then I tried to find a more general approach and came up with this ForcedType<T> template class.
template <typename T>
struct ForcedType {
ForcedType(T v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2);
T m_v;
};
template <typename T>
struct ForcedType<const T&> {
ForcedType(const T& v): m_v(v) {}
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(const T2&);
const T& m_v;
};
template <typename T>
struct ForcedType<T&> {
ForcedType(T& v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2&);
T& m_v;
};
If I'm not mistaken, those three specializations should cover all common use cases. I'm not sure if a specialization for rvalue-reference (on C++11 onwards) is actually needed or the by-value one suffices.
One would use it like this, in case of a function with 3 parameters whose 3rd parameter doesn't allow implicit conversions:
function(ParamType1 param1, ParamType2 param2, ForcedType<ParamType3> param3);

Prohibition of operator << calling

I have some code.
#include <iostream>
template<typename T>
struct Test
{
Test(bool v):flg(v) { }
void func() { }
typedef void (Test::*unspecified)();
operator unspecified() const
{
return flg ? &Test::func : 0;
}
bool flg;
};
template<typename T>
std::ostream& operator << (std::ostream&, typename Test<T>::unspecified);
int main()
{
Test<int> t(true);
std::cout << t << std::endl;
}
Output is
1
It works fine, but i want to get undefined reference. If Test is not template class i get undefined reference. So, why compiler not use operator << for function type and do standart conversion from pointer to class-member to bool?
In typename Test<T>::unspecified, T is in a non-deducible context, since it appears to the left of a ::. Thus your function template is never even considered, and the conversion to unspecified is used as the sole viable overload.
The short answer is simply that "templates don't work like that". Let me know if you want a longer answer.