Is there a way to prevent the pass an object to an ellipsis?
Example:
The ellipsis is used in the following function
int my_printf( const char * format, ... );
And there is an object of some type:
struct Text
{
const char * c_str();
};
Text text;
Is it possible to change struct Text so that the following does not compile?
my_printf("%s", text ); // should fail to compile
my_printf("%s", text.c_str() ); // this was the intention
Changing my_printf to use variadic template arguments instead of an ellipsis is not an option.
Use a static assert:
#include <type_traits>
// test all parameters for being true
template<typename ... Args>
constexpr bool all(Args ... args) {
return (... && args);
}
// test if it's a class, error message has the name of the class
template<typename T>
struct not_an_object {
static const bool value = !std::is_class<T>::value;
static_assert(value, "no classes please");
};
// won't compile if there's a class object in the parameters
template<typename ... Ts, typename =
std::enable_if_t<all(not_an_object<Ts>::value ...)>>
void a_print(char const*fmt, Ts ... e){
my_printf(fmt, e...);
}
In case deleting the copy constructor is an option the usage in ellipsis results in an error.
Unfortunately declaring the copy constructor as explicit does not result in an error.
#include "stdio.h"
struct A
{
A( const A & ) = delete;
//explicit A( const A & ) = default;
A() {}
int m = 3;
};
int main ()
{
A a;
printf("%d", a); // error
}
Related
I want to use a fold expression but the function will only ever be used with one known parameter pack.
i.e.
template <class... Types>
Foo fn_impl(Arg arg) {
// here, a fold expression involving Types... that returns a Foo
}
Foo fn(Arg arg) {
return fn_impl<Bar, Baz>(arg);
}
And that's it, fn_impl won't ever be used again.
Is there a way to make this less verbose?
Ideally, I'd like to write the implementation of fn in its body, without a separate implementation function (which adds noise, imo).
I know I could "unroll" the fold expression with the types in the parameter pack by hand, but in this case, using a fold expression is just very convenient to make the implementation of fn not too verbose.
Here's a complete example, see highlighted QUESTION comment:
#include <cassert>
#include <cstdio>
#include <memory>
struct Base {
virtual ~Base() {}
virtual const char *get_name() const = 0;
};
template <class Derived> struct Base_CRTP : public Base {
const char *get_name() const final {
return static_cast<const Derived *>(this)->name;
}
};
struct A : Base_CRTP<A> {
static constexpr const char *name = "A";
};
struct B : Base_CRTP<B> {
static constexpr const char *name = "B";
};
#define ITest_DERIVED_CLASSES A, B
// QUESTION: Can this be entirely moved into the definition of #1?
template <class IType, class... Types>
std::unique_ptr<IType> make_by_class_index___impl(int class_index) {
int i = 0;
std::unique_ptr<IType> ret;
([&] {
if (i++ == class_index)
ret = std::make_unique<Types>();
return ret != nullptr;
}() ||
...);
return ret;
}
// #1
std::unique_ptr<Base> make_by_class_index(int class_index) {
return make_by_class_index___impl<Base, ITest_DERIVED_CLASSES>(class_index);
}
template <class... Types> void print_pack_names() { (puts(Types::name), ...); }
int main() {
print_pack_names<ITest_DERIVED_CLASSES>();
puts("");
auto p = make_by_class_index(0);
assert(p != nullptr);
printf("p name: %s\n", p->get_name());
auto p2 = make_by_class_index(1);
assert(p2 != nullptr);
printf("p2 name: %s\n", p2->get_name());
auto p3 = make_by_class_index(99);
assert(p3 == nullptr);
}
In lack of sufficient details, let's assume without loss of generality that Arg is int that that Foo, Bar and Baz are defined as follows:
struct Foo { int x; };
struct Bar { static constexpr int foo() { return 1; } };
struct Baz { static constexpr int foo() { return 2; } };
If you may use C++20 you can migrate a) a variadic function which contains a fold expression and b) a call to site to it, e.g.:
template <typename... Types> Foo fn_impl(int arg) {
return { arg + (Types::foo() + ...) };
}
// at call site
fn_impl<Bar, Baz>(arg);
into a single generic immediately invoked lambda, leveraging that P0428R2 (introduced in C++20) allows template heads for generic lambdas:
Foo fn(int arg) {
return []<typename... Types>(int arg) -> Foo {
return { arg + (Types::foo() + ...) };
}
.operator()<Bar, Baz>(arg);
}
This arguably looks quite complex, though, particularly as you need to use the operator name syntax to provide explicit template arguments for the generic lambdas. The separate function approach is arguably easier to follow for future maintainers.
Is it possible specify a template argument, that would never match to a basic type, such as an int? I'm heavily fighting ambiguities. So for example:
template<class T> void Function(const T& x) { SetString(x.GetString()); };
That would work only if there's a method GetString in T, but if the compiler sees this function, it tries to uses it even if T is just int for example.
Method 1
You can use std::enable_if as shown below:
C++11
//this function template will not be used with fundamental types
template<class T> typename std::enable_if<!std::is_fundamental<T>::value>::type Function(const T& x)
{
SetString(x.GetString());
};
Demo
C++17
template<class T> typename std::enable_if_t<!std::is_fundamental_v<T>> Function(const T& x)
{
SetString(x.GetString());
};
Demo
Method 2
We can make use of SFINAE. Here we use decltype and the comma operator to define the return type of the function template.
//this function template will work if the class type has a const member function named GetString
template <typename T> auto Function (T const & x) -> decltype( x.GetString(), void())
{
SetString(x.GetString());
};
Demo
Here we've used trailing return type syntax to specify the return type of the function template.
If the problem i that int doesn't support a GetString() method, maybe instead of disable the function for fundamental types, you could enable it if (and only if) the template type has a GetString() const method accepting a call without arguments.
Observe that GetString() must be const, because Function() receive a const reference, so you can call GetString() inside Function() only if GetString() is a const method.
The following is a full compiling example. Observe the failure in the bar1 and bar2 cases
#include <string>
void SetString (std::string const &)
{ }
struct foo // class with a conformat GetString method
{ std::string GetString () const { return "abc"; } };
struct bar1 // class with a not conformant (not const) GetString method
{ std::string GetString () { return "123"; } };
struct bar2 // class with a not conformant (require a int) GetString method
{ std::string GetString (int) const { return "123"; } };
struct bar3 // class without a GetString method
{ };
template <typename T>
auto Function (T const & x) -> decltype( x.GetString(), void())
{ SetString(x.GetString()); }
int main()
{
Function(foo{}); // compile
// Function(bar1{}); // compilation error (GetString isn't const)
// Function(bar2{}); // compilation error (GetString require a int)
// Function(bar3{}); // compilation error (no GetString method)
// Function(0); // compilation error (no GetString method)
}
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 have two classes test1 and test2:
struct test1
{
int r;
test1() {}
test1(int value) : r(value) {}
test1 foo() const;
};
struct test2
{
int r;
test2() {}
test2(int value) : r(value) {}
};
template <typename t>
struct data_t
{
static const t one;
};
template <> const test1 data_t<test1>::one = test1(1);
template <> const test2 data_t<test2>::one = test2(1);
then i created a function to do somthing:
template <typename t, const t& value>
t do_somthing()
{ return value; };
the action of do_something is straightforward, it returns a copy of value, so in main function:
int main()
{
test1 r = do_somthing<test1, data_t<test1>::one>();
}
the problem happens when implementing test1::foo
test1 test1::foo() const
{ return do_somthing<test1, *this>(); }
the compiler stops with error:
'this' : can only be referenced inside non-static member functions
with *this it becomes test1 const& which acceptable as 2nd parameter, so why this error?
When you call a template method with explicit mention of parameters like,
do_somthing<test1, data_t<test1>::one>(); //(1) ok
do_somthing<test1, *this>(); // (2) error
then compiler expects that the explicit arguments should be compile time constants. In your (2)nd case, *this is not resolvable to a compile time constant, so you are getting the compiler error.
Change the definition to below:
template <typename t>
t do_somthing(const t& value)
{ return value; };
and now when you call as,
do_somthing<test1>(*this); // (2) ok
it should work. Because, now const t& doesn't need to be a compile time constant, even though it's resolved at compile time.
The compiler tells you exactly why this won't work, 'this' : can only be referenced inside non-static member functions. It's not usable in any other context.
If you want to templatize this function in this manner you have to use a template function that has the ability to deduce the argument type at compile time, like this:
template <class T>
T copy_value(const T& value)
{
return value;
}
class A
{
public:
A clone()
{
return copy_value(*this);
}
};
int main()
{
int x = 999;
int y = copy_value(x);
double d = 9.99;
double e = copy_value(d);
std::string s = "Test";
std::string t = copy_value(s);
return 0;
}
In each of the above examples, the function template is deduced at compile time so the compiler can properly generate the code necessary. Your classes that you use with this template should be appropriately copyable, and copy-constructable.
I would like to define a template function but disallow instantiation with a particular type. Note that in general all types are allowed and the generic template works, I just want to disallow using a few specific types.
For example, in the code below I wish to prevent using double with the template. This doesn't actually prevent the instantiation, but just causes a linker error by not having the function defined.
template<typename T>
T convert( char const * in )
{ return T(); }
//this way creates a linker error
template<>
double convert<double>( char const * in );
int main()
{
char const * str = "1234";
int a = convert<int>( str );
double b = convert<double>( str );
}
The code is just a demonstration, obviously the convert function must do something more.
Question: In the above code how can I produce a compiler error when trying to use the convert<double> instantiation?
The closest related question I can find is How to intentionally cause a compile-time error on template instantiation It deals with a class, not a function.
The reason I need to do this is because the types I wish to block will actually compile and do something with the generic version. That's however not supposed to be part of the contract of the function and may not be supported on all platforms/compilers and in future versions. Thus I'd like to prevent using it at all.
I would use a static assert within your function call to create the proper failure during function instantiation:
template<typename T>
class is_double{ static const int value = false; }
template<>
class is_double<double>{ static const int value = true; }
template<typename T>
T convert( const char *argument ){
BOOST_STATIC_ASSERT( !is_double<T>::value );
//rest of code
}
And that should work within a function.
If you don't want to rely on static_assert or make the code portable pre-C++0x, use this:
template<class T>
void func(){
typedef char ERROR_in_the_matrix[std::is_same<T,double>::value? -1 : 1];
}
int main(){
func<int>(); // no error
func<double>(); // error: negative subscript
}
You could use a functor instead of a function:
template<typename T>
struct convert {
T operator()(char const * in) const { return T(); }
};
template<> struct convert<double>;
int main()
{
char const * str = "1234";
int a = convert<int>()( str );
double b = convert<double>()( str ); // error in this line
return 0;
}
This will give you an error at the point of instantiation.
By adding helper function you will get the wanted behaviour:
template<typename T>
struct convert_helper {
T operator()(char const * in) const { return T(); }
};
template<> struct convert_helper<double>;
template<typename T>
T convert( char const * in ) { return convert_helper<T>()( in ); }
int main()
{
char const * str = "1234";
int a = convert<int>( str );
double b = convert<double>( str );
return 0;
}
Consider Boost disable_if and Boost TypeTraits
Take a look at How can I write a function template for all types with a particular type trait?
This is an example:
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
template<typename T>
T convert( char const * in,
typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0 )
{ return T(); }
int main()
{
char const * str = "1234";
int a = convert<int>( str );
double b = convert<double>( str );
return 0;
}
This is the compilation error for the string
double b = convert<double>( str );
1>.\simple_no_stlport.cpp(14) : error
C2770: invalid explicit template
argument(s) for 'T convert(const char
*,boost::disable_if,T>::type
*)' 1> .\simple_no_stlport.cpp(5) : see
declaration of 'convert'