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)
{
...
}
Related
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; };
I want to define a template function that gets one argument passed by value for all types but std::string (and const char*).
template<typename T>
void foo( T value )
{
// some code using value
}
The std::string version should behave exactly as the template version, but have its parameter passed by const&.
What is the best approach to do what I want without duplicating the body of foo()?
The best I was able to think is to wrap the code using value inside another function, and then call it inside all versions of foo() (the template version and the std::string overload). Is there another way? For example, is it possible to call the template version from within the std::string overload?
EDIT
What I want to know is a good rule of thumb for avoiding code duplication among various specializations and overloads. What is a good pattern to follow? Shall I define a wrapper function for the body and then call that from within all overloads/specializations, or there is another way?
In order to avoid code duplication, the answer by 101010 can be extended to actually call the template from within the overload:
#include <string>
#include <iostream>
#include <type_traits>
#include <boost/core/demangle.hpp>
template<typename T>
void foo( T value )
{
std::cout << "inside template" << std::endl;
std::cout << boost::core::demangle(typeid(value).name()) << std::endl;
}
void foo(const std::string &value)
{
std::cout << "inside const string overload" << std::endl;
foo<const std::string&>(value);
}
int main()
{
foo(10);
foo(std::string("hello"));
return 0;
}
output
inside template
int
inside const string overload
inside template
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >
live example
Simple solution: provide an overload for std::string:
void foo( std::string const &value ) {
// some code using value
}
I think what you are looking for is rvalue signature in C++ 11.
Its as simple as:
#include <iostream>
#include <string>
template<typename T>
void foo(T&& value)
{
std::cout << "was passed by refernece:" << std::is_lvalue_reference<T&&>::value << std::endl;
std::cout << value << std::endl;
}
int main()
{
std::string text = "hello";
foo(text);
foo(1);
}
You can either pass the parameter by reference or by value and the rvalue rules will use the appropriate type.
You can define a type-trait-like class that will convert std::string to std::string& and will keep the type for all other types:
template<class T>
struct helper {
typedef T type;
};
template<>
struct helper<std::string> {
typedef std::string& type; // or const std::string& type if you want
};
template<typename T>
void foo( typename helper<T>::type value, T value2 )
{
value = value2;
}
int main()
{
int a = 10;
foo(a, 42);
std::cout << a << std::endl; // prints 10
std::string s = "abc";
foo(s, std::string("def"));
std::cout << s << std::endl; // prints def
}
Full example: http://coliru.stacked-crooked.com/a/96cf78e6c4846172
UPD: as noted by #PiotrSkotnicki, having only one parameter makes type-deduction fail. However, I will keep the answer as it might be helpful in case you indeed have several parameters of type T or if you are ok with specifying explicit template parameter to foo.
UPD2: To solve the type-deduction problem, you may add another wrapper:
template<typename T>
void foo_helper( typename helper<T>::type value )
{
value = T();
}
template<typename T>
void foo(T& value)
{
foo_helper<T>(value);
}
This still might have some problems, so whether this is applicable to your usecase, is up to you to decide.
use std::enable_if + std::is_convertibale:
template<typename T>
typename std::enable_if<!std::is_convertible<T,std::string>::value>::type foo( T value )
{
// some code using value
}
EDIT: Just to clarify "t" is successfully called when casted. The compiler knows and does state that it is a function pointer that takes an argument of type int. I supply a null int pointer to break the loop because it is calling itself recursively. It may just be a bug in the compiler.
I am trying to call a function from a template function argument.
I would assume that it would be possible to call the function without explicit casting but that does not seem to be the case. Using VC2013.
template<typename T>
void func(T t)
{
printf("calling func...\n");
if (t)
{
((void(__cdecl*)(int))t)((int)nullptr); // explicit casting is successful
t ((int)nullptr); // compile error: ``term does not evaluate to a function taking 1 arguments``
}
}
void main()
{
auto pe = func < int > ;
auto pf = func < void(__cdecl*)(int) >;
pf(pe);
}
You have the error for func<int> which becomes:
void func(int t)
{
printf("calling func...\n");
if (t)
{
((void(__cdecl*)(int))t)((int)nullptr); // bad casting
t ((int)nullptr); // compile error: int is not a callable object
}
}
When t is an int, of course you can't treat it like a function. You'll have to specialize the template for ints or use a different function. Also, please forget that there are C-style casts, they only serve to shoot yourself into the foot.
I don't understand what do you want exactly. But maybe something like this ?:
#include <iostream>
#include <type_traits>
template<typename T>
void call_helper(T value, std::true_type) // value is function
{
std::cout << "Function" << std::endl;
value(0);
}
template<typename T>
void call_helper(T value, std::false_type) // value is NOT function
{
std::cout << "Not function" << std::endl;
std::cout << value << std::endl;
}
template<typename T>
void call(T value)
{
call_helper(value, std::is_function<typename std::remove_pointer<T>::type>());
}
int main()
{
void (*f)(int) = call<int>;
call(f);
}
live example: http://rextester.com/DIYYZ43213
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);
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.